netlink: Break out sender_name
[secnet] / netlink.c
CommitLineData
2fe58dfd
SE
1/* User-kernel network link */
2
ff05a229 3/* See RFCs 791, 792, 1123 and 1812 */
2fe58dfd 4
ff05a229
SE
5/* The netlink device is actually a router. Tunnels are unnumbered
6 point-to-point lines (RFC1812 section 2.2.7); the router has a
7 single address (the 'router-id'). */
8
9/* This is where we currently have the anti-spoofing paranoia - before
10 sending a packet to the kernel we check that the tunnel it came
11 over could reasonably have produced it. */
12
13
14/* Points to note from RFC1812 (which may require changes in this
15 file):
16
173.3.4 Maximum Transmission Unit - MTU
18
19 The MTU of each logical interface MUST be configurable within the
20 range of legal MTUs for the interface.
21
22 Many Link Layer protocols define a maximum frame size that may be
23 sent. In such cases, a router MUST NOT allow an MTU to be set which
24 would allow sending of frames larger than those allowed by the Link
25 Layer protocol. However, a router SHOULD be willing to receive a
26 packet as large as the maximum frame size even if that is larger than
27 the MTU.
28
294.2.1 A router SHOULD count datagrams discarded.
30
314.2.2.1 Source route options - we probably should implement processing
32of source routes, even though mostly the security policy will prevent
33their use.
34
355.3.13.4 Source Route Options
36
37 A router MUST implement support for source route options in forwarded
38 packets. A router MAY implement a configuration option that, when
39 enabled, causes all source-routed packets to be discarded. However,
40 such an option MUST NOT be enabled by default.
41
425.3.13.5 Record Route Option
43
44 Routers MUST support the Record Route option in forwarded packets.
45
46 A router MAY provide a configuration option that, if enabled, will
47 cause the router to ignore (i.e., pass through unchanged) Record
48 Route options in forwarded packets. If provided, such an option MUST
49 default to enabling the record-route. This option should not affect
50 the processing of Record Route options in datagrams received by the
51 router itself (in particular, Record Route options in ICMP echo
52 requests will still be processed according to Section [4.3.3.6]).
53
545.3.13.6 Timestamp Option
55
56 Routers MUST support the timestamp option in forwarded packets. A
57 timestamp value MUST follow the rules given [INTRO:2].
58
59 If the flags field = 3 (timestamp and prespecified address), the
60 router MUST add its timestamp if the next prespecified address
61 matches any of the router's IP addresses. It is not necessary that
62 the prespecified address be either the address of the interface on
63 which the packet arrived or the address of the interface over which
64 it will be sent.
65
66
674.2.2.7 Fragmentation: RFC 791 Section 3.2
68
69 Fragmentation, as described in [INTERNET:1], MUST be supported by a
70 router.
71
724.2.2.8 Reassembly: RFC 791 Section 3.2
73
74 As specified in the corresponding section of [INTRO:2], a router MUST
75 support reassembly of datagrams that it delivers to itself.
76
774.2.2.9 Time to Live: RFC 791 Section 3.2
78
79 Note in particular that a router MUST NOT check the TTL of a packet
80 except when forwarding it.
81
82 A router MUST NOT discard a datagram just because it was received
83 with TTL equal to zero or one; if it is to the router and otherwise
84 valid, the router MUST attempt to receive it.
85
86 On messages the router originates, the IP layer MUST provide a means
87 for the transport layer to set the TTL field of every datagram that
88 is sent. When a fixed TTL value is used, it MUST be configurable.
89
90
918.1 The Simple Network Management Protocol - SNMP
928.1.1 SNMP Protocol Elements
93
94 Routers MUST be manageable by SNMP [MGT:3]. The SNMP MUST operate
95 using UDP/IP as its transport and network protocols.
96
97
98*/
2fe58dfd 99
3b83c932 100#include <string.h>
59230b9b
IJ
101#include <assert.h>
102#include <limits.h>
8689b3a9 103#include "secnet.h"
2fe58dfd 104#include "util.h"
7138d0c5 105#include "ipaddr.h"
9d3a4132 106#include "netlink.h"
042a8da9 107#include "process.h"
2fe58dfd 108
a0b107b8
IJ
109#ifdef NETLINK_DEBUG
110#define MDEBUG(...) Message(M_DEBUG, __VA_ARGS__)
111#else /* !NETLINK_DEBUG */
112#define MDEBUG(...) ((void)0)
113#endif /* !NETLINK_DEBUG */
114
ff05a229
SE
115#define ICMP_TYPE_ECHO_REPLY 0
116
117#define ICMP_TYPE_UNREACHABLE 3
118#define ICMP_CODE_NET_UNREACHABLE 0
119#define ICMP_CODE_PROTOCOL_UNREACHABLE 2
120#define ICMP_CODE_FRAGMENTATION_REQUIRED 4
121#define ICMP_CODE_NET_PROHIBITED 13
122
123#define ICMP_TYPE_ECHO_REQUEST 8
124
125#define ICMP_TYPE_TIME_EXCEEDED 11
126#define ICMP_CODE_TTL_EXCEEDED 0
127
4efd681a 128/* Generic IP checksum routine */
211cd627 129static inline uint16_t ip_csum(const uint8_t *iph,int32_t count)
2fe58dfd 130{
4efd681a
SE
131 register uint32_t sum=0;
132
133 while (count>1) {
134 sum+=ntohs(*(uint16_t *)iph);
135 iph+=2;
136 count-=2;
137 }
138 if(count>0)
139 sum+=*(uint8_t *)iph;
140 while (sum>>16)
141 sum=(sum&0xffff)+(sum>>16);
142 return htons(~sum);
2fe58dfd
SE
143}
144
4efd681a
SE
145#ifdef i386
146/*
147 * This is a version of ip_compute_csum() optimized for IP headers,
148 * which always checksum on 4 octet boundaries.
149 *
150 * By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
151 * Arnt Gulbrandsen.
152 */
211cd627 153static inline uint16_t ip_fast_csum(const uint8_t *iph, int32_t ihl) {
4efd681a
SE
154 uint32_t sum;
155
20d324b6
SE
156 __asm__ __volatile__(
157 "movl (%1), %0 ;\n"
158 "subl $4, %2 ;\n"
159 "jbe 2f ;\n"
160 "addl 4(%1), %0 ;\n"
161 "adcl 8(%1), %0 ;\n"
162 "adcl 12(%1), %0 ;\n"
163"1: adcl 16(%1), %0 ;\n"
164 "lea 4(%1), %1 ;\n"
165 "decl %2 ;\n"
166 "jne 1b ;\n"
167 "adcl $0, %0 ;\n"
168 "movl %0, %2 ;\n"
169 "shrl $16, %0 ;\n"
170 "addw %w2, %w0 ;\n"
171 "adcl $0, %0 ;\n"
172 "notl %0 ;\n"
173"2: ;\n"
4efd681a
SE
174 /* Since the input registers which are loaded with iph and ipl
175 are modified, we must also specify them as outputs, or gcc
176 will assume they contain their original values. */
177 : "=r" (sum), "=r" (iph), "=r" (ihl)
20d324b6
SE
178 : "1" (iph), "2" (ihl)
179 : "memory");
4efd681a
SE
180 return sum;
181}
182#else
1caa23ff 183static inline uint16_t ip_fast_csum(uint8_t *iph, int32_t ihl)
2fe58dfd 184{
1caa23ff 185 assert(ihl < INT_MAX/4);
4efd681a
SE
186 return ip_csum(iph,ihl*4);
187}
188#endif
189
190struct iphdr {
191#if defined (WORDS_BIGENDIAN)
192 uint8_t version:4,
193 ihl:4;
194#else
195 uint8_t ihl:4,
196 version:4;
197#endif
198 uint8_t tos;
199 uint16_t tot_len;
200 uint16_t id;
a6768d7c 201 uint16_t frag;
eff13010
IJ
202#define IPHDR_FRAG_OFF ((uint16_t)0x1fff)
203#define IPHDR_FRAG_MORE ((uint16_t)0x2000)
204#define IPHDR_FRAG_DONT ((uint16_t)0x4000)
205/* reserved 0x8000 */
4efd681a
SE
206 uint8_t ttl;
207 uint8_t protocol;
208 uint16_t check;
209 uint32_t saddr;
210 uint32_t daddr;
211 /* The options start here. */
212};
213
214struct icmphdr {
215 struct iphdr iph;
216 uint8_t type;
217 uint8_t code;
218 uint16_t check;
cfd79482 219 union icmpinfofield {
4efd681a
SE
220 uint32_t unused;
221 struct {
222 uint8_t pointer;
223 uint8_t unused1;
224 uint16_t unused2;
225 } pprob;
226 uint32_t gwaddr;
227 struct {
228 uint16_t id;
229 uint16_t seq;
230 } echo;
f3d69e41
IJ
231 struct {
232 uint16_t unused;
233 uint16_t mtu;
234 } fragneeded;
4efd681a
SE
235 } d;
236};
cfd79482
IJ
237
238static const union icmpinfofield icmp_noinfo;
4efd681a 239
dbe11c20
IJ
240static const char *sender_name(struct netlink_client *sender /* or NULL */)
241{
242 return sender?sender->name:"(local)";
243}
244
70dc107b
SE
245static void netlink_packet_deliver(struct netlink *st,
246 struct netlink_client *client,
247 struct buffer_if *buf);
4efd681a 248
ff05a229
SE
249/* XXX RFC1812 4.3.2.5:
250 All other ICMP error messages (Destination Unreachable,
251 Redirect, Time Exceeded, and Parameter Problem) SHOULD have their
252 precedence value set to 6 (INTERNETWORK CONTROL) or 7 (NETWORK
253 CONTROL). The IP Precedence value for these error messages MAY be
254 settable.
255 */
4efd681a
SE
256static struct icmphdr *netlink_icmp_tmpl(struct netlink *st,
257 uint32_t dest,uint16_t len)
258{
259 struct icmphdr *h;
260
261 BUF_ALLOC(&st->icmp,"netlink_icmp_tmpl");
3abd18e8 262 buffer_init(&st->icmp,calculate_max_start_pad());
4efd681a
SE
263 h=buf_append(&st->icmp,sizeof(*h));
264
265 h->iph.version=4;
266 h->iph.ihl=5;
267 h->iph.tos=0;
268 h->iph.tot_len=htons(len+(h->iph.ihl*4)+8);
269 h->iph.id=0;
a6768d7c 270 h->iph.frag=0;
ff05a229 271 h->iph.ttl=255; /* XXX should be configurable */
4efd681a
SE
272 h->iph.protocol=1;
273 h->iph.saddr=htonl(st->secnet_address);
274 h->iph.daddr=htonl(dest);
275 h->iph.check=0;
276 h->iph.check=ip_fast_csum((uint8_t *)&h->iph,h->iph.ihl);
277 h->check=0;
278 h->d.unused=0;
279
280 return h;
281}
282
283/* Fill in the ICMP checksum field correctly */
284static void netlink_icmp_csum(struct icmphdr *h)
285{
1caa23ff 286 int32_t len;
4efd681a
SE
287
288 len=ntohs(h->iph.tot_len)-(4*h->iph.ihl);
289 h->check=0;
290 h->check=ip_csum(&h->type,len);
291}
292
293/* RFC1122:
294 * An ICMP error message MUST NOT be sent as the result of
295 * receiving:
296 *
297 * * an ICMP error message, or
298 *
299 * * a datagram destined to an IP broadcast or IP multicast
300 * address, or
301 *
302 * * a datagram sent as a link-layer broadcast, or
303 *
304 * * a non-initial fragment, or
305 *
306 * * a datagram whose source address does not define a single
307 * host -- e.g., a zero address, a loopback address, a
308 * broadcast address, a multicast address, or a Class E
309 * address.
310 */
311static bool_t netlink_icmp_may_reply(struct buffer_if *buf)
312{
313 struct iphdr *iph;
8dea8d37 314 struct icmphdr *icmph;
4efd681a
SE
315 uint32_t source;
316
975820aa 317 if (buf->size < (int)sizeof(struct icmphdr)) return False;
4efd681a 318 iph=(struct iphdr *)buf->start;
8dea8d37
SE
319 icmph=(struct icmphdr *)buf->start;
320 if (iph->protocol==1) {
321 switch(icmph->type) {
686b7f1d
IJ
322 /* Based on http://www.iana.org/assignments/icmp-parameters/icmp-parameters.xhtml#icmp-parameters-types
323 * as retrieved Thu, 20 Mar 2014 00:16:44 +0000.
324 * Deprecated, reserved, unassigned and experimental
325 * options are treated as not safe to reply to.
326 */
327 case 0: /* Echo Reply */
328 case 8: /* Echo */
329 case 13: /* Timestamp */
330 case 14: /* Timestamp Reply */
331 return True;
332 default:
8dea8d37
SE
333 return False;
334 }
335 }
4efd681a 336 /* How do we spot broadcast destination addresses? */
a6768d7c 337 if (ntohs(iph->frag)&IPHDR_FRAG_OFF) return False;
4efd681a
SE
338 source=ntohl(iph->saddr);
339 if (source==0) return False;
340 if ((source&0xff000000)==0x7f000000) return False;
341 /* How do we spot broadcast source addresses? */
342 if ((source&0xf0000000)==0xe0000000) return False; /* Multicast */
343 if ((source&0xf0000000)==0xf0000000) return False; /* Class E */
344 return True;
345}
346
347/* How much of the original IP packet do we include in its ICMP
348 response? The header plus up to 64 bits. */
ff05a229
SE
349
350/* XXX TODO RFC1812:
3514.3.2.3 Original Message Header
352
353 Historically, every ICMP error message has included the Internet
354 header and at least the first 8 data bytes of the datagram that
355 triggered the error. This is no longer adequate, due to the use of
356 IP-in-IP tunneling and other technologies. Therefore, the ICMP
357 datagram SHOULD contain as much of the original datagram as possible
358 without the length of the ICMP datagram exceeding 576 bytes. The
359 returned IP header (and user data) MUST be identical to that which
360 was received, except that the router is not required to undo any
361 modifications to the IP header that are normally performed in
362 forwarding that were performed before the error was detected (e.g.,
363 decrementing the TTL, or updating options). Note that the
364 requirements of Section [4.3.3.5] supersede this requirement in some
365 cases (i.e., for a Parameter Problem message, if the problem is in a
366 modified field, the router must undo the modification). See Section
367 [4.3.3.5]).
368 */
4efd681a
SE
369static uint16_t netlink_icmp_reply_len(struct buffer_if *buf)
370{
975820aa 371 if (buf->size < (int)sizeof(struct iphdr)) return 0;
4efd681a
SE
372 struct iphdr *iph=(struct iphdr *)buf->start;
373 uint16_t hlen,plen;
374
375 hlen=iph->ihl*4;
376 /* We include the first 8 bytes of the packet data, provided they exist */
377 hlen+=8;
378 plen=ntohs(iph->tot_len);
379 return (hlen>plen?plen:hlen);
380}
381
70dc107b
SE
382/* client indicates where the packet we're constructing a response to
383 comes from. NULL indicates the host. */
4efd681a 384static void netlink_icmp_simple(struct netlink *st, struct buffer_if *buf,
cfd79482
IJ
385 uint8_t type, uint8_t code,
386 union icmpinfofield info)
4efd681a 387{
4efd681a
SE
388 struct icmphdr *h;
389 uint16_t len;
390
391 if (netlink_icmp_may_reply(buf)) {
975820aa 392 struct iphdr *iph=(struct iphdr *)buf->start;
4efd681a
SE
393 len=netlink_icmp_reply_len(buf);
394 h=netlink_icmp_tmpl(st,ntohl(iph->saddr),len);
cfd79482 395 h->type=type; h->code=code; h->d=info;
4efd681a
SE
396 memcpy(buf_append(&st->icmp,len),buf->start,len);
397 netlink_icmp_csum(h);
70dc107b 398 netlink_packet_deliver(st,NULL,&st->icmp);
4efd681a
SE
399 BUF_ASSERT_FREE(&st->icmp);
400 }
401}
402
403/*
404 * RFC1122: 3.1.2.2 MUST silently discard any IP frame that fails the
405 * checksum.
ff05a229 406 * RFC1812: 4.2.2.5 MUST discard messages containing invalid checksums.
4efd681a
SE
407 *
408 * Is the datagram acceptable?
409 *
410 * 1. Length at least the size of an ip header
411 * 2. Version of 4
412 * 3. Checksums correctly.
413 * 4. Doesn't have a bogus length
414 */
d714da29
IJ
415static bool_t netlink_check(struct netlink *st, struct buffer_if *buf,
416 char *errmsgbuf, int errmsgbuflen)
4efd681a 417{
d714da29
IJ
418#define BAD(...) do{ \
419 snprintf(errmsgbuf,errmsgbuflen,__VA_ARGS__); \
420 return False; \
421 }while(0)
422
975820aa 423 if (buf->size < (int)sizeof(struct iphdr)) BAD("len %"PRIu32"",buf->size);
4efd681a 424 struct iphdr *iph=(struct iphdr *)buf->start;
1caa23ff 425 int32_t len;
4efd681a 426
d714da29
IJ
427 if (iph->ihl < 5) BAD("ihl %u",iph->ihl);
428 if (iph->version != 4) BAD("version %u",iph->version);
429 if (buf->size < iph->ihl*4) BAD("size %"PRId32"<%u*4",buf->size,iph->ihl);
430 if (ip_fast_csum((uint8_t *)iph, iph->ihl)!=0) BAD("csum");
4efd681a
SE
431 len=ntohs(iph->tot_len);
432 /* There should be no padding */
d714da29
IJ
433 if (buf->size!=len) BAD("len %"PRId32"!=%"PRId32,buf->size,len);
434 if (len<(iph->ihl<<2)) BAD("len %"PRId32"<(%u<<2)",len,iph->ihl);
4efd681a
SE
435 /* XXX check that there's no source route specified */
436 return True;
d714da29
IJ
437
438#undef BAD
4efd681a
SE
439}
440
f3d69e41
IJ
441static const char *fragment_filter_header(uint8_t *base, long *hlp)
442{
443 const int fixedhl = sizeof(struct iphdr);
444 long hl = *hlp;
445 const uint8_t *ipend = base + hl;
446 uint8_t *op = base + fixedhl;
447 const uint8_t *ip = op;
448
449 while (ip < ipend) {
450 uint8_t opt = ip[0];
451 int remain = ipend - ip;
452 if (opt == 0x00) /* End of Options List */ break;
453 if (opt == 0x01) /* No Operation */ continue;
454 if (remain < 2) return "IPv4 options truncated at length";
455 int optlen = ip[1];
456 if (remain < optlen) return "IPv4 options truncated in option";
457 if (opt & 0x80) /* copy */ {
458 memmove(op, ip, optlen);
459 op += optlen;
460 }
461 ip += optlen;
462 }
463 while ((hl = (op - base)) & 0x3)
464 *op++ = 0x00 /* End of Option List */;
465 ((struct iphdr*)base)->ihl = hl >> 2;
466 *hlp = hl;
467
468 return 0;
469}
470
471/* Fragment or send ICMP Fragmentation Needed */
472static void netlink_maybe_fragment(struct netlink *st,
473 netlink_deliver_fn *deliver,
474 void *deliver_dst,
475 const char *delivery_name,
476 int32_t mtu,
477 uint32_t source, uint32_t dest,
478 struct buffer_if *buf)
479{
480 struct iphdr *iph=(struct iphdr*)buf->start;
481 long hl = iph->ihl*4;
482 const char *ssource = ipaddr_to_string(source);
483
484 if (buf->size <= mtu) {
485 deliver(deliver_dst, buf);
486 return;
487 }
488
489 MDEBUG("%s: fragmenting %s->%s org.size=%"PRId32"\n",
490 st->name, ssource, delivery_name, buf->size);
491
492#define BADFRAG(m, ...) \
493 Message(M_WARNING, \
494 "%s: fragmenting packet from source %s" \
495 " for transmission via %s: " m "\n", \
496 st->name, ssource, delivery_name, \
497 ## __VA_ARGS__);
498
499 unsigned orig_frag = ntohs(iph->frag);
500
501 if (orig_frag&IPHDR_FRAG_DONT) {
502 union icmpinfofield info =
503 { .fragneeded = { .unused = 0, .mtu = htons(mtu) } };
504 netlink_icmp_simple(st,buf,
505 ICMP_TYPE_UNREACHABLE,
506 ICMP_CODE_FRAGMENTATION_REQUIRED,
507 info);
508 BUF_FREE(buf);
509 return;
510 }
511 if (mtu < hl + 8) {
512 BADFRAG("mtu %"PRId32" too small", mtu);
513 BUF_FREE(buf);
514 return;
515 }
516
517 /* we (ab)use the icmp buffer to stash the original packet */
518 struct buffer_if *orig = &st->icmp;
519 BUF_ALLOC(orig,"netlink_client_deliver fragment orig");
520 buffer_copy(orig,buf);
521 BUF_FREE(buf);
522
523 const uint8_t *startindata = orig->start + hl;
524 const uint8_t *indata = startindata;
525 const uint8_t *endindata = orig->start + orig->size;
526 _Bool filtered = 0;
527
528 for (;;) {
529 /* compute our fragment offset */
530 long dataoffset = indata - startindata
531 + (orig_frag & IPHDR_FRAG_OFF)*8;
532 assert(!(dataoffset & 7));
533 if (dataoffset > IPHDR_FRAG_OFF*8) {
534 BADFRAG("ultimate fragment offset out of range");
535 break;
536 }
537
538 BUF_ALLOC(buf,"netlink_client_deliver fragment frag");
539 buffer_init(buf,calculate_max_start_pad());
540
541 /* copy header (possibly filtered); will adjust in a bit */
542 struct iphdr *fragh = buf_append(buf, hl);
543 memcpy(fragh, orig->start, hl);
544
545 /* decide how much payload to copy and copy it */
546 long avail = mtu - hl;
547 long remain = endindata - indata;
548 long use = avail < remain ? (avail & ~(long)7) : remain;
549 memcpy(buf_append(buf, use), indata, use);
550 indata += use;
551
552 _Bool last_frag = indata >= endindata;
553
554 /* adjust the header */
555 fragh->tot_len = htons(buf->size);
556 fragh->frag =
557 htons((orig_frag & ~IPHDR_FRAG_OFF) |
558 (last_frag ? 0 : IPHDR_FRAG_MORE) |
559 (dataoffset >> 3));
560 fragh->check = 0;
561 fragh->check = ip_fast_csum((const void*)fragh, fragh->ihl);
562
563 /* actually send it */
564 deliver(deliver_dst, buf);
565 if (last_frag)
566 break;
567
568 /* after copying the header for the first frag,
569 * we filter the header for the remaining frags */
570 if (!filtered++) {
571 const char *bad = fragment_filter_header(orig->start, &hl);
572 if (bad) { BADFRAG("%s", bad); break; }
573 }
574 }
575
576 BUF_FREE(orig);
577
578#undef BADFRAG
579}
580
7b6abafa 581/* Deliver a packet _to_ client; used after we have decided
55bc97e6
IJ
582 * what to do with it (and just to check that the client has
583 * actually registered a delivery function with us). */
7b6abafa
IJ
584static void netlink_client_deliver(struct netlink *st,
585 struct netlink_client *client,
586 uint32_t source, uint32_t dest,
587 struct buffer_if *buf)
588{
55bc97e6
IJ
589 if (!client->deliver) {
590 string_t s,d;
591 s=ipaddr_to_string(source);
592 d=ipaddr_to_string(dest);
593 Message(M_ERR,"%s: dropping %s->%s, client not registered\n",
594 st->name,s,d);
595 free(s); free(d);
596 BUF_FREE(buf);
597 return;
598 }
f3d69e41
IJ
599 netlink_maybe_fragment(st, client->deliver,client->dst,client->name,
600 client->mtu, source,dest,buf);
7b6abafa
IJ
601 client->outcount++;
602}
603
f928f069
IJ
604/* Deliver a packet to the host; used after we have decided that that
605 * is what to do with it. */
606static void netlink_host_deliver(struct netlink *st,
607 uint32_t source, uint32_t dest,
608 struct buffer_if *buf)
609{
f3d69e41
IJ
610 netlink_maybe_fragment(st, st->deliver_to_host,st->dst,"(host)",
611 st->mtu, source,dest,buf);
f928f069
IJ
612 st->outcount++;
613}
614
f2b711bd 615/* Deliver a packet. "sender"==NULL for packets from the host and packets
d3fe100d 616 generated internally in secnet. */
70dc107b 617static void netlink_packet_deliver(struct netlink *st,
f2b711bd 618 struct netlink_client *sender,
70dc107b 619 struct buffer_if *buf)
4efd681a 620{
975820aa
IJ
621 if (buf->size < (int)sizeof(struct iphdr)) {
622 Message(M_ERR,"%s: trying to deliver a too-short packet"
dbe11c20 623 " from %s!\n",st->name, sender_name(sender));
975820aa
IJ
624 BUF_FREE(buf);
625 return;
626 }
627
4efd681a
SE
628 struct iphdr *iph=(struct iphdr *)buf->start;
629 uint32_t dest=ntohl(iph->daddr);
70dc107b
SE
630 uint32_t source=ntohl(iph->saddr);
631 uint32_t best_quality;
469fd1d9
SE
632 bool_t allow_route=False;
633 bool_t found_allowed=False;
70dc107b
SE
634 int best_match;
635 int i;
2fe58dfd 636
4efd681a 637 BUF_ASSERT_USED(buf);
2fe58dfd 638
4efd681a 639 if (dest==st->secnet_address) {
4f5e39ec 640 Message(M_ERR,"%s: trying to deliver a packet to myself!\n",st->name);
4efd681a 641 BUF_FREE(buf);
2fe58dfd
SE
642 return;
643 }
4efd681a 644
f2b711bd 645 /* Packets from the host (sender==NULL) may always be routed. Packets
469fd1d9 646 from clients with the allow_route option will also be routed. */
f2b711bd 647 if (!sender || (sender && (sender->options & OPT_ALLOWROUTE)))
469fd1d9
SE
648 allow_route=True;
649
650 /* If !allow_route, we check the routing table anyway, and if
651 there's a suitable route with OPT_ALLOWROUTE set we use it. If
652 there's a suitable route, but none with OPT_ALLOWROUTE set then
653 we generate ICMP 'communication with destination network
654 administratively prohibited'. */
655
656 best_quality=0;
657 best_match=-1;
d3fe100d
SE
658 for (i=0; i<st->n_clients; i++) {
659 if (st->routes[i]->up &&
660 ipset_contains_addr(st->routes[i]->networks,dest)) {
469fd1d9
SE
661 /* It's an available route to the correct destination. But is
662 it better than the one we already have? */
663
664 /* If we have already found an allowed route then we don't
665 bother looking at routes we're not allowed to use. If
666 we don't yet have an allowed route we'll consider any. */
667 if (!allow_route && found_allowed) {
d3fe100d 668 if (!(st->routes[i]->options&OPT_ALLOWROUTE)) continue;
70dc107b 669 }
469fd1d9 670
d3fe100d 671 if (st->routes[i]->link_quality>best_quality
469fd1d9 672 || best_quality==0) {
d3fe100d 673 best_quality=st->routes[i]->link_quality;
469fd1d9 674 best_match=i;
d3fe100d 675 if (st->routes[i]->options&OPT_ALLOWROUTE)
469fd1d9
SE
676 found_allowed=True;
677 /* If quality isn't perfect we may wish to
678 consider kicking the tunnel with a 0-length
679 packet to prompt it to perform a key setup.
680 Then it'll eventually decide it's up or
681 down. */
682 /* If quality is perfect and we're allowed to use the
683 route we don't need to search any more. */
684 if (best_quality>=MAXIMUM_LINK_QUALITY &&
685 (allow_route || found_allowed)) break;
4efd681a 686 }
70dc107b 687 }
469fd1d9
SE
688 }
689 if (best_match==-1) {
690 /* The packet's not going down a tunnel. It might (ought to)
691 be for the host. */
794f2398 692 if (ipset_contains_addr(st->networks,dest)) {
f928f069 693 netlink_host_deliver(st,source,dest,buf);
70dc107b
SE
694 BUF_ASSERT_FREE(buf);
695 } else {
469fd1d9
SE
696 string_t s,d;
697 s=ipaddr_to_string(source);
698 d=ipaddr_to_string(dest);
ff05a229 699 Message(M_DEBUG,"%s: don't know where to deliver packet "
469fd1d9
SE
700 "(s=%s, d=%s)\n", st->name, s, d);
701 free(s); free(d);
311e11e4 702 netlink_icmp_simple(st,buf,ICMP_TYPE_UNREACHABLE,
cfd79482 703 ICMP_CODE_NET_UNREACHABLE, icmp_noinfo);
70dc107b 704 BUF_FREE(buf);
2fe58dfd 705 }
469fd1d9
SE
706 } else {
707 if (!allow_route &&
d3fe100d 708 !(st->routes[best_match]->options&OPT_ALLOWROUTE)) {
469fd1d9
SE
709 string_t s,d;
710 s=ipaddr_to_string(source);
711 d=ipaddr_to_string(dest);
712 /* We have a usable route but aren't allowed to use it.
713 Generate ICMP destination unreachable: communication
714 with destination network administratively prohibited */
715 Message(M_NOTICE,"%s: denied forwarding for packet (s=%s, d=%s)\n",
716 st->name,s,d);
717 free(s); free(d);
718
311e11e4 719 netlink_icmp_simple(st,buf,ICMP_TYPE_UNREACHABLE,
cfd79482 720 ICMP_CODE_NET_PROHIBITED, icmp_noinfo);
469fd1d9 721 BUF_FREE(buf);
469fd1d9 722 } else {
ea7ec970 723 if (best_quality>0) {
7b6abafa
IJ
724 netlink_client_deliver(st,st->routes[best_match],
725 source,dest,buf);
ea7ec970
SE
726 BUF_ASSERT_FREE(buf);
727 } else {
728 /* Generate ICMP destination unreachable */
311e11e4 729 netlink_icmp_simple(st,buf,
cfd79482
IJ
730 ICMP_TYPE_UNREACHABLE,
731 ICMP_CODE_NET_UNREACHABLE,
732 icmp_noinfo);
ea7ec970
SE
733 BUF_FREE(buf);
734 }
469fd1d9 735 }
2fe58dfd 736 }
70dc107b 737 BUF_ASSERT_FREE(buf);
4efd681a
SE
738}
739
70dc107b 740static void netlink_packet_forward(struct netlink *st,
f2b711bd 741 struct netlink_client *sender,
70dc107b 742 struct buffer_if *buf)
4efd681a 743{
975820aa 744 if (buf->size < (int)sizeof(struct iphdr)) return;
4efd681a
SE
745 struct iphdr *iph=(struct iphdr *)buf->start;
746
747 BUF_ASSERT_USED(buf);
748
749 /* Packet has already been checked */
750 if (iph->ttl<=1) {
751 /* Generate ICMP time exceeded */
311e11e4 752 netlink_icmp_simple(st,buf,ICMP_TYPE_TIME_EXCEEDED,
cfd79482 753 ICMP_CODE_TTL_EXCEEDED,icmp_noinfo);
4efd681a
SE
754 BUF_FREE(buf);
755 return;
756 }
757 iph->ttl--;
758 iph->check=0;
759 iph->check=ip_fast_csum((uint8_t *)iph,iph->ihl);
760
f2b711bd 761 netlink_packet_deliver(st,sender,buf);
4efd681a
SE
762 BUF_ASSERT_FREE(buf);
763}
764
9d3a4132 765/* Deal with packets addressed explicitly to us */
70dc107b 766static void netlink_packet_local(struct netlink *st,
f2b711bd 767 struct netlink_client *sender,
70dc107b 768 struct buffer_if *buf)
4efd681a
SE
769{
770 struct icmphdr *h;
771
469fd1d9
SE
772 st->localcount++;
773
975820aa
IJ
774 if (buf->size < (int)sizeof(struct icmphdr)) {
775 Message(M_WARNING,"%s: short packet addressed to secnet; "
776 "ignoring it\n",st->name);
777 BUF_FREE(buf);
778 return;
779 }
4efd681a
SE
780 h=(struct icmphdr *)buf->start;
781
6e3fd952
IJ
782 unsigned fraginfo = ntohs(h->iph.frag);
783 if ((fraginfo&(IPHDR_FRAG_OFF|IPHDR_FRAG_MORE))!=0) {
784 if (!(fraginfo & IPHDR_FRAG_OFF))
785 /* report only for first fragment */
786 Message(M_WARNING,"%s: fragmented packet addressed to secnet; "
787 "ignoring it\n",st->name);
4efd681a
SE
788 BUF_FREE(buf);
789 return;
790 }
791
792 if (h->iph.protocol==1) {
793 /* It's ICMP */
ff05a229 794 if (h->type==ICMP_TYPE_ECHO_REQUEST && h->code==0) {
4efd681a
SE
795 /* ICMP echo-request. Special case: we re-use the buffer
796 to construct the reply. */
ff05a229 797 h->type=ICMP_TYPE_ECHO_REPLY;
4efd681a
SE
798 h->iph.daddr=h->iph.saddr;
799 h->iph.saddr=htonl(st->secnet_address);
ff05a229 800 h->iph.ttl=255;
4efd681a
SE
801 h->iph.check=0;
802 h->iph.check=ip_fast_csum((uint8_t *)h,h->iph.ihl);
803 netlink_icmp_csum(h);
70dc107b 804 netlink_packet_deliver(st,NULL,buf);
4efd681a
SE
805 return;
806 }
807 Message(M_WARNING,"%s: unknown incoming ICMP\n",st->name);
808 } else {
809 /* Send ICMP protocol unreachable */
311e11e4 810 netlink_icmp_simple(st,buf,ICMP_TYPE_UNREACHABLE,
cfd79482 811 ICMP_CODE_PROTOCOL_UNREACHABLE,icmp_noinfo);
4efd681a
SE
812 BUF_FREE(buf);
813 return;
814 }
815
816 BUF_FREE(buf);
817}
818
9d3a4132
SE
819/* If cid==NULL packet is from host, otherwise cid specifies which tunnel
820 it came from. */
f2b711bd 821static void netlink_incoming(struct netlink *st, struct netlink_client *sender,
469fd1d9 822 struct buffer_if *buf)
4efd681a 823{
4efd681a
SE
824 uint32_t source,dest;
825 struct iphdr *iph;
d714da29 826 char errmsgbuf[50];
f2b711bd 827 const char *sourcedesc=sender?sender->name:"host";
4efd681a
SE
828
829 BUF_ASSERT_USED(buf);
a28d65a5 830
d714da29
IJ
831 if (!netlink_check(st,buf,errmsgbuf,sizeof(errmsgbuf))) {
832 Message(M_WARNING,"%s: bad IP packet from %s: %s\n",
a28d65a5 833 st->name,sourcedesc,
d714da29 834 errmsgbuf);
4efd681a
SE
835 BUF_FREE(buf);
836 return;
837 }
e8b1adac 838 assert(buf->size >= (int)sizeof(struct iphdr));
4efd681a
SE
839 iph=(struct iphdr *)buf->start;
840
841 source=ntohl(iph->saddr);
842 dest=ntohl(iph->daddr);
843
d3fe100d
SE
844 /* Check source. If we don't like the source, there's no point
845 generating ICMP because we won't know how to get it to the
846 source of the packet. */
f2b711bd 847 if (sender) {
c6f79b17
SE
848 /* Check that the packet source is appropriate for the tunnel
849 it came down */
f2b711bd 850 if (!ipset_contains_addr(sender->networks,source)) {
9d3a4132
SE
851 string_t s,d;
852 s=ipaddr_to_string(source);
853 d=ipaddr_to_string(dest);
854 Message(M_WARNING,"%s: packet from tunnel %s with bad "
f2b711bd 855 "source address (s=%s,d=%s)\n",st->name,sender->name,s,d);
9d3a4132
SE
856 free(s); free(d);
857 BUF_FREE(buf);
858 return;
859 }
860 } else {
c6f79b17
SE
861 /* Check that the packet originates in our configured local
862 network, and hasn't been forwarded from elsewhere or
863 generated with the wrong source address */
794f2398 864 if (!ipset_contains_addr(st->networks,source)) {
9d3a4132
SE
865 string_t s,d;
866 s=ipaddr_to_string(source);
867 d=ipaddr_to_string(dest);
868 Message(M_WARNING,"%s: outgoing packet with bad source address "
869 "(s=%s,d=%s)\n",st->name,s,d);
870 free(s); free(d);
871 BUF_FREE(buf);
872 return;
873 }
4efd681a 874 }
c6f79b17 875
794f2398
SE
876 /* If this is a point-to-point device we don't examine the
877 destination address at all; we blindly send it down our
878 one-and-only registered tunnel, or to the host, depending on
d3fe100d
SE
879 where it came from. It's up to external software to check
880 address validity and generate ICMP, etc. */
c6f79b17 881 if (st->ptp) {
f2b711bd 882 if (sender) {
f928f069 883 netlink_host_deliver(st,source,dest,buf);
c6f79b17 884 } else {
7b6abafa 885 netlink_client_deliver(st,st->clients,source,dest,buf);
c6f79b17
SE
886 }
887 BUF_ASSERT_FREE(buf);
888 return;
889 }
890
d3fe100d
SE
891 /* st->secnet_address needs checking before matching destination
892 addresses */
2fe58dfd 893 if (dest==st->secnet_address) {
f2b711bd 894 netlink_packet_local(st,sender,buf);
4efd681a 895 BUF_ASSERT_FREE(buf);
2fe58dfd
SE
896 return;
897 }
f2b711bd 898 netlink_packet_forward(st,sender,buf);
4efd681a
SE
899 BUF_ASSERT_FREE(buf);
900}
901
469fd1d9
SE
902static void netlink_inst_incoming(void *sst, struct buffer_if *buf)
903{
904 struct netlink_client *c=sst;
905 struct netlink *st=c->nst;
906
907 netlink_incoming(st,c,buf);
908}
909
910static void netlink_dev_incoming(void *sst, struct buffer_if *buf)
911{
912 struct netlink *st=sst;
913
914 netlink_incoming(st,NULL,buf);
915}
916
d3fe100d 917static void netlink_set_quality(void *sst, uint32_t quality)
4efd681a 918{
d3fe100d
SE
919 struct netlink_client *c=sst;
920 struct netlink *st=c->nst;
4efd681a 921
d3fe100d
SE
922 c->link_quality=quality;
923 c->up=(c->link_quality==LINK_QUALITY_DOWN)?False:True;
924 if (c->options&OPT_SOFTROUTE) {
925 st->set_routes(st->dst,c);
4efd681a 926 }
4efd681a
SE
927}
928
d3fe100d
SE
929static void netlink_output_subnets(struct netlink *st, uint32_t loglevel,
930 struct subnet_list *snets)
4efd681a 931{
1caa23ff 932 int32_t i;
d3fe100d 933 string_t net;
4efd681a 934
d3fe100d
SE
935 for (i=0; i<snets->entries; i++) {
936 net=subnet_to_string(snets->list[i]);
937 Message(loglevel,"%s ",net);
938 free(net);
9d3a4132 939 }
4efd681a
SE
940}
941
042a8da9 942static void netlink_dump_routes(struct netlink *st, bool_t requested)
9d3a4132
SE
943{
944 int i;
945 string_t net;
042a8da9 946 uint32_t c=M_INFO;
9d3a4132 947
042a8da9 948 if (requested) c=M_WARNING;
469fd1d9
SE
949 if (st->ptp) {
950 net=ipaddr_to_string(st->secnet_address);
34d3bf4c 951 Message(c,"%s: point-to-point (remote end is %s); routes: ",
469fd1d9 952 st->name, net);
9d3a4132 953 free(net);
d3fe100d 954 netlink_output_subnets(st,c,st->clients->subnets);
469fd1d9
SE
955 Message(c,"\n");
956 } else {
957 Message(c,"%s: routing table:\n",st->name);
d3fe100d
SE
958 for (i=0; i<st->n_clients; i++) {
959 netlink_output_subnets(st,c,st->routes[i]->subnets);
ff05a229 960 Message(c,"-> tunnel %s (%s,mtu %d,%s routes,%s,"
ea7ec970 961 "quality %d,use %d,pri %lu)\n",
d3fe100d 962 st->routes[i]->name,
ff05a229
SE
963 st->routes[i]->up?"up":"down",
964 st->routes[i]->mtu,
d3fe100d
SE
965 st->routes[i]->options&OPT_SOFTROUTE?"soft":"hard",
966 st->routes[i]->options&OPT_ALLOWROUTE?"free":"restricted",
d3fe100d 967 st->routes[i]->link_quality,
ea7ec970
SE
968 st->routes[i]->outcount,
969 (unsigned long)st->routes[i]->priority);
469fd1d9
SE
970 }
971 net=ipaddr_to_string(st->secnet_address);
972 Message(c,"%s/32 -> netlink \"%s\" (use %d)\n",
973 net,st->name,st->localcount);
9d3a4132 974 free(net);
794f2398
SE
975 for (i=0; i<st->subnets->entries; i++) {
976 net=subnet_to_string(st->subnets->list[i]);
977 Message(c,"%s ",net);
469fd1d9
SE
978 free(net);
979 }
794f2398
SE
980 if (i>0)
981 Message(c,"-> host (use %d)\n",st->outcount);
9d3a4132
SE
982 }
983}
984
d3fe100d
SE
985/* ap is a pointer to a member of the routes array */
986static int netlink_compare_client_priority(const void *ap, const void *bp)
70dc107b 987{
d3fe100d
SE
988 const struct netlink_client *const*a=ap;
989 const struct netlink_client *const*b=bp;
70dc107b 990
d3fe100d
SE
991 if ((*a)->priority==(*b)->priority) return 0;
992 if ((*a)->priority<(*b)->priority) return 1;
70dc107b
SE
993 return -1;
994}
995
996static void netlink_phase_hook(void *sst, uint32_t new_phase)
997{
998 struct netlink *st=sst;
999 struct netlink_client *c;
1caa23ff 1000 int32_t i;
70dc107b
SE
1001
1002 /* All the networks serviced by the various tunnels should now
1003 * have been registered. We build a routing table by sorting the
d3fe100d 1004 * clients by priority. */
bb9d0561
IJ
1005 st->routes=safe_malloc_ary(sizeof(*st->routes),st->n_clients,
1006 "netlink_phase_hook");
70dc107b
SE
1007 /* Fill the table */
1008 i=0;
59230b9b
IJ
1009 for (c=st->clients; c; c=c->next) {
1010 assert(i<INT_MAX);
d3fe100d 1011 st->routes[i++]=c;
59230b9b 1012 }
d3fe100d
SE
1013 /* Sort the table in descending order of priority */
1014 qsort(st->routes,st->n_clients,sizeof(*st->routes),
1015 netlink_compare_client_priority);
9d3a4132 1016
042a8da9
SE
1017 netlink_dump_routes(st,False);
1018}
1019
1020static void netlink_signal_handler(void *sst, int signum)
1021{
1022 struct netlink *st=sst;
1023 Message(M_INFO,"%s: route dump requested by SIGUSR1\n",st->name);
1024 netlink_dump_routes(st,True);
70dc107b
SE
1025}
1026
1caa23ff 1027static void netlink_inst_set_mtu(void *sst, int32_t new_mtu)
d3fe100d
SE
1028{
1029 struct netlink_client *c=sst;
1030
1031 c->mtu=new_mtu;
1032}
1033
469fd1d9 1034static void netlink_inst_reg(void *sst, netlink_deliver_fn *deliver,
1c085348 1035 void *dst, uint32_t *localmtu_r)
469fd1d9
SE
1036{
1037 struct netlink_client *c=sst;
1c085348 1038 struct netlink *st=c->nst;
469fd1d9 1039
469fd1d9
SE
1040 c->deliver=deliver;
1041 c->dst=dst;
1c085348
IJ
1042
1043 if (localmtu_r)
1044 *localmtu_r=st->mtu;
469fd1d9
SE
1045}
1046
1047static struct flagstr netlink_option_table[]={
1048 { "soft", OPT_SOFTROUTE },
1049 { "allow-route", OPT_ALLOWROUTE },
1050 { NULL, 0}
1051};
1052/* This is the routine that gets called when the closure that's
1053 returned by an invocation of a netlink device closure (eg. tun,
1054 userv-ipif) is invoked. It's used to create routes and pass in
1055 information about them; the closure it returns is used by site
1056 code. */
1057static closure_t *netlink_inst_create(struct netlink *st,
1058 struct cloc loc, dict_t *dict)
1059{
1060 struct netlink_client *c;
1061 string_t name;
794f2398 1062 struct ipset *networks;
1caa23ff
IJ
1063 uint32_t options,priority;
1064 int32_t mtu;
794f2398 1065 list_t *l;
469fd1d9
SE
1066
1067 name=dict_read_string(dict, "name", True, st->name, loc);
1068
794f2398
SE
1069 l=dict_lookup(dict,"routes");
1070 if (!l)
1071 cfgfatal(loc,st->name,"required parameter \"routes\" not found\n");
1072 networks=string_list_to_ipset(l,loc,st->name,"routes");
469fd1d9
SE
1073 options=string_list_to_word(dict_lookup(dict,"options"),
1074 netlink_option_table,st->name);
1075
d3fe100d
SE
1076 priority=dict_read_number(dict,"priority",False,st->name,loc,0);
1077 mtu=dict_read_number(dict,"mtu",False,st->name,loc,0);
1078
1079 if ((options&OPT_SOFTROUTE) && !st->set_routes) {
469fd1d9
SE
1080 cfgfatal(loc,st->name,"this netlink device does not support "
1081 "soft routes.\n");
1082 return NULL;
1083 }
1084
1085 if (options&OPT_SOFTROUTE) {
1086 /* XXX for now we assume that soft routes require root privilege;
1087 this may not always be true. The device driver can tell us. */
1088 require_root_privileges=True;
1089 require_root_privileges_explanation="netlink: soft routes";
1090 if (st->ptp) {
1091 cfgfatal(loc,st->name,"point-to-point netlinks do not support "
1092 "soft routes.\n");
1093 return NULL;
1094 }
1095 }
1096
794f2398
SE
1097 /* Check that nets are a subset of st->remote_networks;
1098 refuse to register if they are not. */
1099 if (!ipset_is_subset(st->remote_networks,networks)) {
1100 cfgfatal(loc,st->name,"routes are not allowed\n");
469fd1d9
SE
1101 return NULL;
1102 }
1103
1104 c=safe_malloc(sizeof(*c),"netlink_inst_create");
1105 c->cl.description=name;
1106 c->cl.type=CL_NETLINK;
1107 c->cl.apply=NULL;
1108 c->cl.interface=&c->ops;
1109 c->ops.st=c;
1110 c->ops.reg=netlink_inst_reg;
1111 c->ops.deliver=netlink_inst_incoming;
1112 c->ops.set_quality=netlink_set_quality;
d3fe100d 1113 c->ops.set_mtu=netlink_inst_set_mtu;
469fd1d9
SE
1114 c->nst=st;
1115
1116 c->networks=networks;
794f2398 1117 c->subnets=ipset_to_subnet_list(networks);
d3fe100d 1118 c->priority=priority;
469fd1d9
SE
1119 c->deliver=NULL;
1120 c->dst=NULL;
1121 c->name=name;
f208b9a9 1122 c->link_quality=LINK_QUALITY_UNUSED;
d3fe100d
SE
1123 c->mtu=mtu?mtu:st->mtu;
1124 c->options=options;
1125 c->outcount=0;
1126 c->up=False;
1127 c->kup=False;
469fd1d9
SE
1128 c->next=st->clients;
1129 st->clients=c;
59230b9b 1130 assert(st->n_clients < INT_MAX);
d3fe100d 1131 st->n_clients++;
469fd1d9
SE
1132
1133 return &c->cl;
1134}
1135
1136static list_t *netlink_inst_apply(closure_t *self, struct cloc loc,
1137 dict_t *context, list_t *args)
1138{
1139 struct netlink *st=self->interface;
1140
1141 dict_t *dict;
1142 item_t *item;
1143 closure_t *cl;
1144
469fd1d9
SE
1145 item=list_elem(args,0);
1146 if (!item || item->type!=t_dict) {
1147 cfgfatal(loc,st->name,"must have a dictionary argument\n");
1148 }
1149 dict=item->data.dict;
1150
1151 cl=netlink_inst_create(st,loc,dict);
1152
1153 return new_closure(cl);
1154}
1155
9d3a4132
SE
1156netlink_deliver_fn *netlink_init(struct netlink *st,
1157 void *dst, struct cloc loc,
fe5e9cc4 1158 dict_t *dict, cstring_t description,
d3fe100d 1159 netlink_route_fn *set_routes,
9d3a4132 1160 netlink_deliver_fn *to_host)
4efd681a 1161{
c6f79b17 1162 item_t *sa, *ptpa;
794f2398 1163 list_t *l;
c6f79b17 1164
4efd681a
SE
1165 st->dst=dst;
1166 st->cl.description=description;
469fd1d9
SE
1167 st->cl.type=CL_PURE;
1168 st->cl.apply=netlink_inst_apply;
1169 st->cl.interface=st;
4efd681a 1170 st->clients=NULL;
d3fe100d
SE
1171 st->routes=NULL;
1172 st->n_clients=0;
1173 st->set_routes=set_routes;
4efd681a
SE
1174 st->deliver_to_host=to_host;
1175
794f2398 1176 st->name=dict_read_string(dict,"name",False,description,loc);
4efd681a 1177 if (!st->name) st->name=description;
794f2398
SE
1178 l=dict_lookup(dict,"networks");
1179 if (l)
1180 st->networks=string_list_to_ipset(l,loc,st->name,"networks");
1181 else {
4f5e39ec
SE
1182 struct ipset *empty;
1183 empty=ipset_new();
1184 st->networks=ipset_complement(empty);
1185 ipset_free(empty);
794f2398
SE
1186 }
1187 l=dict_lookup(dict,"remote-networks");
1188 if (l) {
1189 st->remote_networks=string_list_to_ipset(l,loc,st->name,
1190 "remote-networks");
1191 } else {
1192 struct ipset *empty;
1193 empty=ipset_new();
1194 st->remote_networks=ipset_complement(empty);
1195 ipset_free(empty);
1196 }
1197
c6f79b17 1198 sa=dict_find_item(dict,"secnet-address",False,"netlink",loc);
469fd1d9 1199 ptpa=dict_find_item(dict,"ptp-address",False,"netlink",loc);
c6f79b17
SE
1200 if (sa && ptpa) {
1201 cfgfatal(loc,st->name,"you may not specify secnet-address and "
1202 "ptp-address in the same netlink device\n");
1203 }
1204 if (!(sa || ptpa)) {
1205 cfgfatal(loc,st->name,"you must specify secnet-address or "
1206 "ptp-address for this netlink device\n");
1207 }
1208 if (sa) {
794f2398 1209 st->secnet_address=string_item_to_ipaddr(sa,"netlink");
c6f79b17
SE
1210 st->ptp=False;
1211 } else {
794f2398 1212 st->secnet_address=string_item_to_ipaddr(ptpa,"netlink");
c6f79b17
SE
1213 st->ptp=True;
1214 }
d3fe100d
SE
1215 /* To be strictly correct we could subtract secnet_address from
1216 networks here. It shouldn't make any practical difference,
794f2398
SE
1217 though, and will make the route dump look complicated... */
1218 st->subnets=ipset_to_subnet_list(st->networks);
4efd681a 1219 st->mtu=dict_read_number(dict, "mtu", False, "netlink", loc, DEFAULT_MTU);
f3d69e41 1220 buffer_new(&st->icmp,MAX(ICMP_BUFSIZE,st->mtu));
469fd1d9
SE
1221 st->outcount=0;
1222 st->localcount=0;
70dc107b
SE
1223
1224 add_hook(PHASE_SETUP,netlink_phase_hook,st);
042a8da9 1225 request_signal_notification(SIGUSR1, netlink_signal_handler, st);
4efd681a 1226
469fd1d9
SE
1227 /* If we're point-to-point then we return a CL_NETLINK directly,
1228 rather than a CL_NETLINK_OLD or pure closure (depending on
1229 compatibility). This CL_NETLINK is for our one and only
1230 client. Our cl.apply function is NULL. */
1231 if (st->ptp) {
1232 closure_t *cl;
1233 cl=netlink_inst_create(st,loc,dict);
1234 st->cl=*cl;
1235 }
1236 return netlink_dev_incoming;
2fe58dfd
SE
1237}
1238
9d3a4132 1239/* No connection to the kernel at all... */
2fe58dfd 1240
9d3a4132 1241struct null {
4efd681a 1242 struct netlink nl;
4efd681a 1243};
2fe58dfd 1244
d3fe100d 1245static bool_t null_set_route(void *sst, struct netlink_client *routes)
4efd681a 1246{
9d3a4132 1247 struct null *st=sst;
d3fe100d
SE
1248
1249 if (routes->up!=routes->kup) {
1250 Message(M_INFO,"%s: setting routes for tunnel %s to state %s\n",
1251 st->nl.name,routes->name,
1252 routes->up?"up":"down");
1253 routes->kup=routes->up;
9d3a4132 1254 return True;
2fe58dfd 1255 }
9d3a4132 1256 return False;
2fe58dfd 1257}
9d3a4132 1258
469fd1d9 1259static void null_deliver(void *sst, struct buffer_if *buf)
2fe58dfd
SE
1260{
1261 return;
1262}
1263
1264static list_t *null_apply(closure_t *self, struct cloc loc, dict_t *context,
1265 list_t *args)
1266{
1267 struct null *st;
4efd681a
SE
1268 item_t *item;
1269 dict_t *dict;
2fe58dfd 1270
4efd681a 1271 st=safe_malloc(sizeof(*st),"null_apply");
2fe58dfd 1272
4efd681a
SE
1273 item=list_elem(args,0);
1274 if (!item || item->type!=t_dict)
1275 cfgfatal(loc,"null-netlink","parameter must be a dictionary\n");
1276
1277 dict=item->data.dict;
1278
9d3a4132
SE
1279 netlink_init(&st->nl,st,loc,dict,"null-netlink",null_set_route,
1280 null_deliver);
4efd681a
SE
1281
1282 return new_closure(&st->nl.cl);
2fe58dfd
SE
1283}
1284
2fe58dfd
SE
1285void netlink_module(dict_t *dict)
1286{
4efd681a 1287 add_closure(dict,"null-netlink",null_apply);
2fe58dfd 1288}