Import release 0.1.10
[secnet] / netlink.c
1 /* User-kernel network link */
2
3 /* Each netlink device is actually a router, with its own IP address.
4 We do things like decreasing the TTL and recalculating the header
5 checksum, generating ICMP, responding to pings, etc. */
6
7 /* This is where we have the anti-spoofing paranoia - before sending a
8 packet to the kernel we check that the tunnel it came over could
9 reasonably have produced it. */
10
11 #include "secnet.h"
12 #include "util.h"
13 #include "ipaddr.h"
14 #include "netlink.h"
15 #include "process.h"
16
17 #define OPT_SOFTROUTE 1
18 #define OPT_ALLOWROUTE 2
19
20 /* Generic IP checksum routine */
21 static inline uint16_t ip_csum(uint8_t *iph,uint32_t count)
22 {
23 register uint32_t sum=0;
24
25 while (count>1) {
26 sum+=ntohs(*(uint16_t *)iph);
27 iph+=2;
28 count-=2;
29 }
30 if(count>0)
31 sum+=*(uint8_t *)iph;
32 while (sum>>16)
33 sum=(sum&0xffff)+(sum>>16);
34 return htons(~sum);
35 }
36
37 #ifdef i386
38 /*
39 * This is a version of ip_compute_csum() optimized for IP headers,
40 * which always checksum on 4 octet boundaries.
41 *
42 * By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
43 * Arnt Gulbrandsen.
44 */
45 static inline uint16_t ip_fast_csum(uint8_t *iph, uint32_t ihl) {
46 uint32_t sum;
47
48 __asm__ __volatile__("
49 movl (%1), %0
50 subl $4, %2
51 jbe 2f
52 addl 4(%1), %0
53 adcl 8(%1), %0
54 adcl 12(%1), %0
55 1: adcl 16(%1), %0
56 lea 4(%1), %1
57 decl %2
58 jne 1b
59 adcl $0, %0
60 movl %0, %2
61 shrl $16, %0
62 addw %w2, %w0
63 adcl $0, %0
64 notl %0
65 2:
66 "
67 /* Since the input registers which are loaded with iph and ipl
68 are modified, we must also specify them as outputs, or gcc
69 will assume they contain their original values. */
70 : "=r" (sum), "=r" (iph), "=r" (ihl)
71 : "1" (iph), "2" (ihl));
72 return sum;
73 }
74 #else
75 static inline uint16_t ip_fast_csum(uint8_t *iph, uint32_t ihl)
76 {
77 return ip_csum(iph,ihl*4);
78 }
79 #endif
80
81 struct iphdr {
82 #if defined (WORDS_BIGENDIAN)
83 uint8_t version:4,
84 ihl:4;
85 #else
86 uint8_t ihl:4,
87 version:4;
88 #endif
89 uint8_t tos;
90 uint16_t tot_len;
91 uint16_t id;
92 uint16_t frag_off;
93 uint8_t ttl;
94 uint8_t protocol;
95 uint16_t check;
96 uint32_t saddr;
97 uint32_t daddr;
98 /* The options start here. */
99 };
100
101 struct icmphdr {
102 struct iphdr iph;
103 uint8_t type;
104 uint8_t code;
105 uint16_t check;
106 union {
107 uint32_t unused;
108 struct {
109 uint8_t pointer;
110 uint8_t unused1;
111 uint16_t unused2;
112 } pprob;
113 uint32_t gwaddr;
114 struct {
115 uint16_t id;
116 uint16_t seq;
117 } echo;
118 } d;
119 };
120
121 static void netlink_packet_deliver(struct netlink *st,
122 struct netlink_client *client,
123 struct buffer_if *buf);
124
125 static struct icmphdr *netlink_icmp_tmpl(struct netlink *st,
126 uint32_t dest,uint16_t len)
127 {
128 struct icmphdr *h;
129
130 BUF_ALLOC(&st->icmp,"netlink_icmp_tmpl");
131 buffer_init(&st->icmp,st->max_start_pad);
132 h=buf_append(&st->icmp,sizeof(*h));
133
134 h->iph.version=4;
135 h->iph.ihl=5;
136 h->iph.tos=0;
137 h->iph.tot_len=htons(len+(h->iph.ihl*4)+8);
138 h->iph.id=0;
139 h->iph.frag_off=0;
140 h->iph.ttl=255;
141 h->iph.protocol=1;
142 h->iph.saddr=htonl(st->secnet_address);
143 h->iph.daddr=htonl(dest);
144 h->iph.check=0;
145 h->iph.check=ip_fast_csum((uint8_t *)&h->iph,h->iph.ihl);
146 h->check=0;
147 h->d.unused=0;
148
149 return h;
150 }
151
152 /* Fill in the ICMP checksum field correctly */
153 static void netlink_icmp_csum(struct icmphdr *h)
154 {
155 uint32_t len;
156
157 len=ntohs(h->iph.tot_len)-(4*h->iph.ihl);
158 h->check=0;
159 h->check=ip_csum(&h->type,len);
160 }
161
162 /* RFC1122:
163 * An ICMP error message MUST NOT be sent as the result of
164 * receiving:
165 *
166 * * an ICMP error message, or
167 *
168 * * a datagram destined to an IP broadcast or IP multicast
169 * address, or
170 *
171 * * a datagram sent as a link-layer broadcast, or
172 *
173 * * a non-initial fragment, or
174 *
175 * * a datagram whose source address does not define a single
176 * host -- e.g., a zero address, a loopback address, a
177 * broadcast address, a multicast address, or a Class E
178 * address.
179 */
180 static bool_t netlink_icmp_may_reply(struct buffer_if *buf)
181 {
182 struct iphdr *iph;
183 struct icmphdr *icmph;
184 uint32_t source;
185
186 iph=(struct iphdr *)buf->start;
187 icmph=(struct icmphdr *)buf->start;
188 if (iph->protocol==1) {
189 switch(icmph->type) {
190 case 3: /* Destination unreachable */
191 case 11: /* Time Exceeded */
192 case 12: /* Parameter Problem */
193 return False;
194 }
195 }
196 /* How do we spot broadcast destination addresses? */
197 if (ntohs(iph->frag_off)&0x1fff) return False; /* Non-initial fragment */
198 source=ntohl(iph->saddr);
199 if (source==0) return False;
200 if ((source&0xff000000)==0x7f000000) return False;
201 /* How do we spot broadcast source addresses? */
202 if ((source&0xf0000000)==0xe0000000) return False; /* Multicast */
203 if ((source&0xf0000000)==0xf0000000) return False; /* Class E */
204 return True;
205 }
206
207 /* How much of the original IP packet do we include in its ICMP
208 response? The header plus up to 64 bits. */
209 static uint16_t netlink_icmp_reply_len(struct buffer_if *buf)
210 {
211 struct iphdr *iph=(struct iphdr *)buf->start;
212 uint16_t hlen,plen;
213
214 hlen=iph->ihl*4;
215 /* We include the first 8 bytes of the packet data, provided they exist */
216 hlen+=8;
217 plen=ntohs(iph->tot_len);
218 return (hlen>plen?plen:hlen);
219 }
220
221 /* client indicates where the packet we're constructing a response to
222 comes from. NULL indicates the host. */
223 static void netlink_icmp_simple(struct netlink *st, struct buffer_if *buf,
224 struct netlink_client *client,
225 uint8_t type, uint8_t code)
226 {
227 struct iphdr *iph=(struct iphdr *)buf->start;
228 struct icmphdr *h;
229 uint16_t len;
230
231 if (netlink_icmp_may_reply(buf)) {
232 len=netlink_icmp_reply_len(buf);
233 h=netlink_icmp_tmpl(st,ntohl(iph->saddr),len);
234 h->type=type; h->code=code;
235 memcpy(buf_append(&st->icmp,len),buf->start,len);
236 netlink_icmp_csum(h);
237 netlink_packet_deliver(st,NULL,&st->icmp);
238 BUF_ASSERT_FREE(&st->icmp);
239 }
240 }
241
242 /*
243 * RFC1122: 3.1.2.2 MUST silently discard any IP frame that fails the
244 * checksum.
245 *
246 * Is the datagram acceptable?
247 *
248 * 1. Length at least the size of an ip header
249 * 2. Version of 4
250 * 3. Checksums correctly.
251 * 4. Doesn't have a bogus length
252 */
253 static bool_t netlink_check(struct netlink *st, struct buffer_if *buf)
254 {
255 struct iphdr *iph=(struct iphdr *)buf->start;
256 uint32_t len;
257
258 if (iph->ihl < 5 || iph->version != 4) return False;
259 if (buf->size < iph->ihl*4) return False;
260 if (ip_fast_csum((uint8_t *)iph, iph->ihl)!=0) return False;
261 len=ntohs(iph->tot_len);
262 /* There should be no padding */
263 if (buf->size!=len || len<(iph->ihl<<2)) return False;
264 /* XXX check that there's no source route specified */
265 return True;
266 }
267
268 /* Deliver a packet. "client" is the _origin_ of the packet, not its
269 destination. */
270 static void netlink_packet_deliver(struct netlink *st,
271 struct netlink_client *client,
272 struct buffer_if *buf)
273 {
274 struct iphdr *iph=(struct iphdr *)buf->start;
275 uint32_t dest=ntohl(iph->daddr);
276 uint32_t source=ntohl(iph->saddr);
277 uint32_t best_quality;
278 bool_t allow_route=False;
279 bool_t found_allowed=False;
280 int best_match;
281 int i;
282
283 BUF_ASSERT_USED(buf);
284
285 if (dest==st->secnet_address) {
286 Message(M_ERR,"%s: trying to deliver a packet to myself!\n");
287 BUF_FREE(buf);
288 return;
289 }
290
291 /* Packets from the host (client==NULL) will always be routed. Packets
292 from clients with the allow_route option will also be routed. */
293 if (!client || (client && (client->options & OPT_ALLOWROUTE)))
294 allow_route=True;
295
296 /* If !allow_route, we check the routing table anyway, and if
297 there's a suitable route with OPT_ALLOWROUTE set we use it. If
298 there's a suitable route, but none with OPT_ALLOWROUTE set then
299 we generate ICMP 'communication with destination network
300 administratively prohibited'. */
301
302 best_quality=0;
303 best_match=-1;
304 for (i=0; i<st->n_routes; i++) {
305 if (st->routes[i].up && subnet_match(&st->routes[i].net,dest)) {
306 /* It's an available route to the correct destination. But is
307 it better than the one we already have? */
308
309 /* If we have already found an allowed route then we don't
310 bother looking at routes we're not allowed to use. If
311 we don't yet have an allowed route we'll consider any. */
312 if (!allow_route && found_allowed) {
313 if (!(st->routes[i].c->options&OPT_ALLOWROUTE)) continue;
314 }
315
316 if (st->routes[i].c->link_quality>best_quality
317 || best_quality==0) {
318 best_quality=st->routes[i].c->link_quality;
319 best_match=i;
320 if (st->routes[i].c->options&OPT_ALLOWROUTE)
321 found_allowed=True;
322 /* If quality isn't perfect we may wish to
323 consider kicking the tunnel with a 0-length
324 packet to prompt it to perform a key setup.
325 Then it'll eventually decide it's up or
326 down. */
327 /* If quality is perfect and we're allowed to use the
328 route we don't need to search any more. */
329 if (best_quality>=MAXIMUM_LINK_QUALITY &&
330 (allow_route || found_allowed)) break;
331 }
332 }
333 }
334 if (best_match==-1) {
335 /* The packet's not going down a tunnel. It might (ought to)
336 be for the host. */
337 if (subnet_matches_list(&st->networks,dest)) {
338 st->deliver_to_host(st->dst,buf);
339 st->outcount++;
340 BUF_ASSERT_FREE(buf);
341 } else {
342 string_t s,d;
343 s=ipaddr_to_string(source);
344 d=ipaddr_to_string(dest);
345 Message(M_ERR,"%s: don't know where to deliver packet "
346 "(s=%s, d=%s)\n", st->name, s, d);
347 free(s); free(d);
348 netlink_icmp_simple(st,buf,client,3,0);
349 BUF_FREE(buf);
350 }
351 } else {
352 if (!allow_route &&
353 !(st->routes[best_match].c->options&OPT_ALLOWROUTE)) {
354 string_t s,d;
355 s=ipaddr_to_string(source);
356 d=ipaddr_to_string(dest);
357 /* We have a usable route but aren't allowed to use it.
358 Generate ICMP destination unreachable: communication
359 with destination network administratively prohibited */
360 Message(M_NOTICE,"%s: denied forwarding for packet (s=%s, d=%s)\n",
361 st->name,s,d);
362 free(s); free(d);
363
364 netlink_icmp_simple(st,buf,client,3,9);
365 BUF_FREE(buf);
366 }
367 if (best_quality>0) {
368 st->routes[best_match].c->deliver(
369 st->routes[best_match].c->dst, buf);
370 st->routes[best_match].outcount++;
371 BUF_ASSERT_FREE(buf);
372 } else {
373 /* Generate ICMP destination unreachable */
374 netlink_icmp_simple(st,buf,client,3,0); /* client==NULL */
375 BUF_FREE(buf);
376 }
377 }
378 BUF_ASSERT_FREE(buf);
379 }
380
381 static void netlink_packet_forward(struct netlink *st,
382 struct netlink_client *client,
383 struct buffer_if *buf)
384 {
385 struct iphdr *iph=(struct iphdr *)buf->start;
386
387 BUF_ASSERT_USED(buf);
388
389 /* Packet has already been checked */
390 if (iph->ttl<=1) {
391 /* Generate ICMP time exceeded */
392 netlink_icmp_simple(st,buf,client,11,0);
393 BUF_FREE(buf);
394 return;
395 }
396 iph->ttl--;
397 iph->check=0;
398 iph->check=ip_fast_csum((uint8_t *)iph,iph->ihl);
399
400 netlink_packet_deliver(st,client,buf);
401 BUF_ASSERT_FREE(buf);
402 }
403
404 /* Deal with packets addressed explicitly to us */
405 static void netlink_packet_local(struct netlink *st,
406 struct netlink_client *client,
407 struct buffer_if *buf)
408 {
409 struct icmphdr *h;
410
411 st->localcount++;
412
413 h=(struct icmphdr *)buf->start;
414
415 if ((ntohs(h->iph.frag_off)&0xbfff)!=0) {
416 Message(M_WARNING,"%s: fragmented packet addressed to secnet; "
417 "ignoring it\n",st->name);
418 BUF_FREE(buf);
419 return;
420 }
421
422 if (h->iph.protocol==1) {
423 /* It's ICMP */
424 if (h->type==8 && h->code==0) {
425 /* ICMP echo-request. Special case: we re-use the buffer
426 to construct the reply. */
427 h->type=0;
428 h->iph.daddr=h->iph.saddr;
429 h->iph.saddr=htonl(st->secnet_address);
430 h->iph.ttl=255; /* Be nice and bump it up again... */
431 h->iph.check=0;
432 h->iph.check=ip_fast_csum((uint8_t *)h,h->iph.ihl);
433 netlink_icmp_csum(h);
434 netlink_packet_deliver(st,NULL,buf);
435 return;
436 }
437 Message(M_WARNING,"%s: unknown incoming ICMP\n",st->name);
438 } else {
439 /* Send ICMP protocol unreachable */
440 netlink_icmp_simple(st,buf,client,3,2);
441 BUF_FREE(buf);
442 return;
443 }
444
445 BUF_FREE(buf);
446 }
447
448 /* If cid==NULL packet is from host, otherwise cid specifies which tunnel
449 it came from. */
450 static void netlink_incoming(struct netlink *st, struct netlink_client *client,
451 struct buffer_if *buf)
452 {
453 uint32_t source,dest;
454 struct iphdr *iph;
455
456 BUF_ASSERT_USED(buf);
457 if (!netlink_check(st,buf)) {
458 Message(M_WARNING,"%s: bad IP packet from %s\n",
459 st->name,client?client->name:"host");
460 BUF_FREE(buf);
461 return;
462 }
463 iph=(struct iphdr *)buf->start;
464
465 source=ntohl(iph->saddr);
466 dest=ntohl(iph->daddr);
467
468 /* Check source */
469 if (client) {
470 /* Check that the packet source is appropriate for the tunnel
471 it came down */
472 if (!subnet_matches_list(&client->networks,source)) {
473 string_t s,d;
474 s=ipaddr_to_string(source);
475 d=ipaddr_to_string(dest);
476 Message(M_WARNING,"%s: packet from tunnel %s with bad "
477 "source address (s=%s,d=%s)\n",st->name,client->name,s,d);
478 free(s); free(d);
479 BUF_FREE(buf);
480 return;
481 }
482 } else {
483 /* Check that the packet originates in our configured local
484 network, and hasn't been forwarded from elsewhere or
485 generated with the wrong source address */
486 if (!subnet_matches_list(&st->networks,source)) {
487 string_t s,d;
488 s=ipaddr_to_string(source);
489 d=ipaddr_to_string(dest);
490 Message(M_WARNING,"%s: outgoing packet with bad source address "
491 "(s=%s,d=%s)\n",st->name,s,d);
492 free(s); free(d);
493 BUF_FREE(buf);
494 return;
495 }
496 }
497
498 /* If this is a point-to-point device we don't examine the packet at
499 all; we blindly send it down our one-and-only registered tunnel,
500 or to the host, depending on where it came from. */
501 if (st->ptp) {
502 if (client) {
503 st->deliver_to_host(st->dst,buf);
504 } else {
505 st->clients->deliver(st->clients->dst,buf);
506 }
507 BUF_ASSERT_FREE(buf);
508 return;
509 }
510
511 /* (st->secnet_address needs checking before matching destination
512 addresses) */
513 if (dest==st->secnet_address) {
514 netlink_packet_local(st,client,buf);
515 BUF_ASSERT_FREE(buf);
516 return;
517 }
518 if (client) {
519 /* Check for free routing */
520 if (!subnet_matches_list(&st->networks,dest)) {
521 string_t s,d;
522 s=ipaddr_to_string(source);
523 d=ipaddr_to_string(dest);
524 Message(M_WARNING,"%s: incoming packet from tunnel %s "
525 "with bad destination address "
526 "(s=%s,d=%s)\n",st->name,client->name,s,d);
527 free(s); free(d);
528 BUF_FREE(buf);
529 return;
530 }
531 }
532 netlink_packet_forward(st,client,buf);
533 BUF_ASSERT_FREE(buf);
534 }
535
536 static void netlink_inst_incoming(void *sst, struct buffer_if *buf)
537 {
538 struct netlink_client *c=sst;
539 struct netlink *st=c->nst;
540
541 netlink_incoming(st,c,buf);
542 }
543
544 static void netlink_dev_incoming(void *sst, struct buffer_if *buf)
545 {
546 struct netlink *st=sst;
547
548 netlink_incoming(st,NULL,buf);
549 }
550
551 static void netlink_set_softlinks(struct netlink *st, struct netlink_client *c,
552 bool_t up, uint32_t quality)
553 {
554 uint32_t i;
555
556 if (!st->routes) return; /* Table has not yet been created */
557 for (i=0; i<st->n_routes; i++) {
558 if (st->routes[i].c==c) {
559 st->routes[i].quality=quality;
560 if (!st->routes[i].hard) {
561 st->routes[i].up=up;
562 st->set_route(st->dst,&st->routes[i]);
563 }
564 }
565 }
566 }
567
568 static void netlink_set_quality(void *sst, uint32_t quality)
569 {
570 struct netlink_client *c=sst;
571 struct netlink *st=c->nst;
572
573 c->link_quality=quality;
574 if (c->link_quality==LINK_QUALITY_DOWN) {
575 netlink_set_softlinks(st,c,False,c->link_quality);
576 } else {
577 netlink_set_softlinks(st,c,True,c->link_quality);
578 }
579 }
580
581 static void netlink_dump_routes(struct netlink *st, bool_t requested)
582 {
583 int i;
584 string_t net;
585 uint32_t c=M_INFO;
586
587 if (requested) c=M_WARNING;
588 if (st->ptp) {
589 net=ipaddr_to_string(st->secnet_address);
590 Message(c,"%s: point-to-point (remote end is %s); routes:\n",
591 st->name, net);
592 free(net);
593 for (i=0; i<st->n_routes; i++) {
594 net=subnet_to_string(&st->routes[i].net);
595 Message(c,"%s ",net);
596 free(net);
597 }
598 Message(c,"\n");
599 } else {
600 Message(c,"%s: routing table:\n",st->name);
601 for (i=0; i<st->n_routes; i++) {
602 net=subnet_to_string(&st->routes[i].net);
603 Message(c,"%s -> tunnel %s (%s,%s route,%s,quality %d,use %d)\n",net,
604 st->routes[i].c->name,
605 st->routes[i].hard?"hard":"soft",
606 st->routes[i].allow_route?"free":"restricted",
607 st->routes[i].up?"up":"down",
608 st->routes[i].quality,
609 st->routes[i].outcount);
610 free(net);
611 }
612 net=ipaddr_to_string(st->secnet_address);
613 Message(c,"%s/32 -> netlink \"%s\" (use %d)\n",
614 net,st->name,st->localcount);
615 free(net);
616 for (i=0; i<st->networks.entries; i++) {
617 net=subnet_to_string(&st->networks.list[i]);
618 Message(c,"%s -> host (use %d)\n",net,st->outcount);
619 free(net);
620 }
621 }
622 }
623
624 static int netlink_compare_route_specificity(const void *ap, const void *bp)
625 {
626 const struct netlink_route *a=ap;
627 const struct netlink_route *b=bp;
628
629 if (a->net.len==b->net.len) return 0;
630 if (a->net.len<b->net.len) return 1;
631 return -1;
632 }
633
634 static void netlink_phase_hook(void *sst, uint32_t new_phase)
635 {
636 struct netlink *st=sst;
637 struct netlink_client *c;
638 uint32_t i,j;
639
640 /* All the networks serviced by the various tunnels should now
641 * have been registered. We build a routing table by sorting the
642 * routes into most-specific-first order. */
643 st->routes=safe_malloc(st->n_routes*sizeof(*st->routes),
644 "netlink_phase_hook");
645 /* Fill the table */
646 i=0;
647 for (c=st->clients; c; c=c->next) {
648 for (j=0; j<c->networks.entries; j++) {
649 st->routes[i].net=c->networks.list[j];
650 st->routes[i].c=c;
651 /* Hard routes are always up;
652 soft routes default to down; routes with no 'deliver' function
653 default to down */
654 st->routes[i].up=c->deliver?
655 (c->options&OPT_SOFTROUTE?False:True):
656 False;
657 st->routes[i].kup=False;
658 st->routes[i].hard=c->options&OPT_SOFTROUTE?False:True;
659 st->routes[i].allow_route=c->options&OPT_ALLOWROUTE?
660 True:False;
661 st->routes[i].quality=c->link_quality;
662 st->routes[i].outcount=0;
663 i++;
664 }
665 }
666 /* ASSERT i==st->n_routes */
667 if (i!=st->n_routes) {
668 fatal("netlink: route count error: expected %d got %d\n",
669 st->n_routes,i);
670 }
671 /* Sort the table in descending order of specificity */
672 qsort(st->routes,st->n_routes,sizeof(*st->routes),
673 netlink_compare_route_specificity);
674
675 netlink_dump_routes(st,False);
676 }
677
678 static void netlink_signal_handler(void *sst, int signum)
679 {
680 struct netlink *st=sst;
681 Message(M_INFO,"%s: route dump requested by SIGUSR1\n",st->name);
682 netlink_dump_routes(st,True);
683 }
684
685 static void netlink_inst_reg(void *sst, netlink_deliver_fn *deliver,
686 void *dst, uint32_t max_start_pad,
687 uint32_t max_end_pad)
688 {
689 struct netlink_client *c=sst;
690 struct netlink *st=c->nst;
691
692 if (max_start_pad > st->max_start_pad) st->max_start_pad=max_start_pad;
693 if (max_end_pad > st->max_end_pad) st->max_end_pad=max_end_pad;
694 c->deliver=deliver;
695 c->dst=dst;
696 }
697
698 static struct flagstr netlink_option_table[]={
699 { "soft", OPT_SOFTROUTE },
700 { "allow-route", OPT_ALLOWROUTE },
701 { NULL, 0}
702 };
703 /* This is the routine that gets called when the closure that's
704 returned by an invocation of a netlink device closure (eg. tun,
705 userv-ipif) is invoked. It's used to create routes and pass in
706 information about them; the closure it returns is used by site
707 code. */
708 static closure_t *netlink_inst_create(struct netlink *st,
709 struct cloc loc, dict_t *dict)
710 {
711 struct netlink_client *c;
712 string_t name;
713 struct subnet_list networks;
714 uint32_t options;
715
716 name=dict_read_string(dict, "name", True, st->name, loc);
717
718 dict_read_subnet_list(dict, "routes", True, st->name, loc,
719 &networks);
720 options=string_list_to_word(dict_lookup(dict,"options"),
721 netlink_option_table,st->name);
722
723 if ((options&OPT_SOFTROUTE) && !st->set_route) {
724 cfgfatal(loc,st->name,"this netlink device does not support "
725 "soft routes.\n");
726 return NULL;
727 }
728
729 if (options&OPT_SOFTROUTE) {
730 /* XXX for now we assume that soft routes require root privilege;
731 this may not always be true. The device driver can tell us. */
732 require_root_privileges=True;
733 require_root_privileges_explanation="netlink: soft routes";
734 if (st->ptp) {
735 cfgfatal(loc,st->name,"point-to-point netlinks do not support "
736 "soft routes.\n");
737 return NULL;
738 }
739 }
740
741 /* Check that nets do not intersect st->exclude_remote_networks;
742 refuse to register if they do. */
743 if (subnet_lists_intersect(&st->exclude_remote_networks,&networks)) {
744 cfgfatal(loc,st->name,"networks intersect with the explicitly "
745 "excluded remote networks\n");
746 return NULL;
747 }
748
749 c=safe_malloc(sizeof(*c),"netlink_inst_create");
750 c->cl.description=name;
751 c->cl.type=CL_NETLINK;
752 c->cl.apply=NULL;
753 c->cl.interface=&c->ops;
754 c->ops.st=c;
755 c->ops.reg=netlink_inst_reg;
756 c->ops.deliver=netlink_inst_incoming;
757 c->ops.set_quality=netlink_set_quality;
758 c->nst=st;
759
760 c->networks=networks;
761 c->deliver=NULL;
762 c->dst=NULL;
763 c->name=name;
764 c->options=options;
765 c->link_quality=LINK_QUALITY_DOWN;
766 c->next=st->clients;
767 st->clients=c;
768 st->n_routes+=networks.entries;
769
770 return &c->cl;
771 }
772
773 static list_t *netlink_inst_apply(closure_t *self, struct cloc loc,
774 dict_t *context, list_t *args)
775 {
776 struct netlink *st=self->interface;
777
778 dict_t *dict;
779 item_t *item;
780 closure_t *cl;
781
782 Message(M_DEBUG_CONFIG,"netlink_inst_apply\n");
783
784 item=list_elem(args,0);
785 if (!item || item->type!=t_dict) {
786 cfgfatal(loc,st->name,"must have a dictionary argument\n");
787 }
788 dict=item->data.dict;
789
790 cl=netlink_inst_create(st,loc,dict);
791
792 return new_closure(cl);
793 }
794
795 netlink_deliver_fn *netlink_init(struct netlink *st,
796 void *dst, struct cloc loc,
797 dict_t *dict, string_t description,
798 netlink_route_fn *set_route,
799 netlink_deliver_fn *to_host)
800 {
801 item_t *sa, *ptpa;
802
803 st->dst=dst;
804 st->cl.description=description;
805 st->cl.type=CL_PURE;
806 st->cl.apply=netlink_inst_apply;
807 st->cl.interface=st;
808 st->max_start_pad=0;
809 st->max_end_pad=0;
810 st->clients=NULL;
811 st->set_route=set_route;
812 st->deliver_to_host=to_host;
813
814 st->name=dict_read_string(dict,"name",False,"netlink",loc);
815 if (!st->name) st->name=description;
816 dict_read_subnet_list(dict, "networks", True, "netlink", loc,
817 &st->networks);
818 dict_read_subnet_list(dict, "exclude-remote-networks", False, "netlink",
819 loc, &st->exclude_remote_networks);
820 sa=dict_find_item(dict,"secnet-address",False,"netlink",loc);
821 ptpa=dict_find_item(dict,"ptp-address",False,"netlink",loc);
822 if (sa && ptpa) {
823 cfgfatal(loc,st->name,"you may not specify secnet-address and "
824 "ptp-address in the same netlink device\n");
825 }
826 if (!(sa || ptpa)) {
827 cfgfatal(loc,st->name,"you must specify secnet-address or "
828 "ptp-address for this netlink device\n");
829 }
830 if (sa) {
831 st->secnet_address=string_to_ipaddr(sa,"netlink");
832 st->ptp=False;
833 } else {
834 st->secnet_address=string_to_ipaddr(ptpa,"netlink");
835 st->ptp=True;
836 }
837 st->mtu=dict_read_number(dict, "mtu", False, "netlink", loc, DEFAULT_MTU);
838 buffer_new(&st->icmp,ICMP_BUFSIZE);
839 st->n_routes=0;
840 st->routes=NULL;
841 st->outcount=0;
842 st->localcount=0;
843
844 add_hook(PHASE_SETUP,netlink_phase_hook,st);
845 request_signal_notification(SIGUSR1, netlink_signal_handler, st);
846
847 /* If we're point-to-point then we return a CL_NETLINK directly,
848 rather than a CL_NETLINK_OLD or pure closure (depending on
849 compatibility). This CL_NETLINK is for our one and only
850 client. Our cl.apply function is NULL. */
851 if (st->ptp) {
852 closure_t *cl;
853 cl=netlink_inst_create(st,loc,dict);
854 st->cl=*cl;
855 }
856 return netlink_dev_incoming;
857 }
858
859 /* No connection to the kernel at all... */
860
861 struct null {
862 struct netlink nl;
863 };
864
865 static bool_t null_set_route(void *sst, struct netlink_route *route)
866 {
867 struct null *st=sst;
868 string_t t;
869
870 if (route->up!=route->kup) {
871 t=subnet_to_string(&route->net);
872 Message(M_INFO,"%s: setting route %s to state %s\n",st->nl.name,
873 t, route->up?"up":"down");
874 free(t);
875 route->kup=route->up;
876 return True;
877 }
878 return False;
879 }
880
881 static void null_deliver(void *sst, struct buffer_if *buf)
882 {
883 return;
884 }
885
886 static list_t *null_apply(closure_t *self, struct cloc loc, dict_t *context,
887 list_t *args)
888 {
889 struct null *st;
890 item_t *item;
891 dict_t *dict;
892
893 st=safe_malloc(sizeof(*st),"null_apply");
894
895 item=list_elem(args,0);
896 if (!item || item->type!=t_dict)
897 cfgfatal(loc,"null-netlink","parameter must be a dictionary\n");
898
899 dict=item->data.dict;
900
901 netlink_init(&st->nl,st,loc,dict,"null-netlink",null_set_route,
902 null_deliver);
903
904 return new_closure(&st->nl.cl);
905 }
906
907 init_module netlink_module;
908 void netlink_module(dict_t *dict)
909 {
910 add_closure(dict,"null-netlink",null_apply);
911 }