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