Import release 0.1.12
[secnet] / netlink.c
CommitLineData
2fe58dfd
SE
1/* User-kernel network link */
2
baa06aeb
SE
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. */
2fe58dfd
SE
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
8689b3a9 11#include "secnet.h"
2fe58dfd 12#include "util.h"
7138d0c5 13#include "ipaddr.h"
9d3a4132 14#include "netlink.h"
042a8da9 15#include "process.h"
2fe58dfd 16
469fd1d9
SE
17#define OPT_SOFTROUTE 1
18#define OPT_ALLOWROUTE 2
19
4efd681a
SE
20/* Generic IP checksum routine */
21static inline uint16_t ip_csum(uint8_t *iph,uint32_t count)
2fe58dfd 22{
4efd681a
SE
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);
2fe58dfd
SE
35}
36
4efd681a
SE
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 */
45static 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
551: 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
652:
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
75static inline uint16_t ip_fast_csum(uint8_t *iph, uint32_t ihl)
2fe58dfd 76{
4efd681a
SE
77 return ip_csum(iph,ihl*4);
78}
79#endif
80
81struct 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
101struct 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
70dc107b
SE
121static void netlink_packet_deliver(struct netlink *st,
122 struct netlink_client *client,
123 struct buffer_if *buf);
4efd681a
SE
124
125static 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 */
153static 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 */
180static bool_t netlink_icmp_may_reply(struct buffer_if *buf)
181{
182 struct iphdr *iph;
8dea8d37 183 struct icmphdr *icmph;
4efd681a
SE
184 uint32_t source;
185
186 iph=(struct iphdr *)buf->start;
8dea8d37
SE
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 }
4efd681a
SE
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. */
209static 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
70dc107b
SE
221/* client indicates where the packet we're constructing a response to
222 comes from. NULL indicates the host. */
4efd681a 223static void netlink_icmp_simple(struct netlink *st, struct buffer_if *buf,
70dc107b 224 struct netlink_client *client,
4efd681a
SE
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);
70dc107b 237 netlink_packet_deliver(st,NULL,&st->icmp);
4efd681a
SE
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 */
253static 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
9d3a4132
SE
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;
4efd681a
SE
261 len=ntohs(iph->tot_len);
262 /* There should be no padding */
9d3a4132 263 if (buf->size!=len || len<(iph->ihl<<2)) return False;
4efd681a
SE
264 /* XXX check that there's no source route specified */
265 return True;
266}
267
469fd1d9 268/* Deliver a packet. "client" is the _origin_ of the packet, not its
d3fe100d
SE
269 destination, and is NULL for packets from the host and packets
270 generated internally in secnet. */
70dc107b
SE
271static void netlink_packet_deliver(struct netlink *st,
272 struct netlink_client *client,
273 struct buffer_if *buf)
4efd681a
SE
274{
275 struct iphdr *iph=(struct iphdr *)buf->start;
276 uint32_t dest=ntohl(iph->daddr);
70dc107b
SE
277 uint32_t source=ntohl(iph->saddr);
278 uint32_t best_quality;
469fd1d9
SE
279 bool_t allow_route=False;
280 bool_t found_allowed=False;
70dc107b
SE
281 int best_match;
282 int i;
2fe58dfd 283
4efd681a 284 BUF_ASSERT_USED(buf);
2fe58dfd 285
4efd681a 286 if (dest==st->secnet_address) {
469fd1d9 287 Message(M_ERR,"%s: trying to deliver a packet to myself!\n");
4efd681a 288 BUF_FREE(buf);
2fe58dfd
SE
289 return;
290 }
4efd681a 291
d3fe100d 292 /* Packets from the host (client==NULL) may always be routed. Packets
469fd1d9
SE
293 from clients with the allow_route option will also be routed. */
294 if (!client || (client && (client->options & OPT_ALLOWROUTE)))
295 allow_route=True;
296
297 /* If !allow_route, we check the routing table anyway, and if
298 there's a suitable route with OPT_ALLOWROUTE set we use it. If
299 there's a suitable route, but none with OPT_ALLOWROUTE set then
300 we generate ICMP 'communication with destination network
301 administratively prohibited'. */
302
303 best_quality=0;
304 best_match=-1;
d3fe100d
SE
305 for (i=0; i<st->n_clients; i++) {
306 if (st->routes[i]->up &&
307 ipset_contains_addr(st->routes[i]->networks,dest)) {
469fd1d9
SE
308 /* It's an available route to the correct destination. But is
309 it better than the one we already have? */
310
311 /* If we have already found an allowed route then we don't
312 bother looking at routes we're not allowed to use. If
313 we don't yet have an allowed route we'll consider any. */
314 if (!allow_route && found_allowed) {
d3fe100d 315 if (!(st->routes[i]->options&OPT_ALLOWROUTE)) continue;
70dc107b 316 }
469fd1d9 317
d3fe100d 318 if (st->routes[i]->link_quality>best_quality
469fd1d9 319 || best_quality==0) {
d3fe100d 320 best_quality=st->routes[i]->link_quality;
469fd1d9 321 best_match=i;
d3fe100d 322 if (st->routes[i]->options&OPT_ALLOWROUTE)
469fd1d9
SE
323 found_allowed=True;
324 /* If quality isn't perfect we may wish to
325 consider kicking the tunnel with a 0-length
326 packet to prompt it to perform a key setup.
327 Then it'll eventually decide it's up or
328 down. */
329 /* If quality is perfect and we're allowed to use the
330 route we don't need to search any more. */
331 if (best_quality>=MAXIMUM_LINK_QUALITY &&
332 (allow_route || found_allowed)) break;
4efd681a 333 }
70dc107b 334 }
469fd1d9
SE
335 }
336 if (best_match==-1) {
337 /* The packet's not going down a tunnel. It might (ought to)
338 be for the host. */
794f2398 339 if (ipset_contains_addr(st->networks,dest)) {
469fd1d9
SE
340 st->deliver_to_host(st->dst,buf);
341 st->outcount++;
70dc107b
SE
342 BUF_ASSERT_FREE(buf);
343 } else {
469fd1d9
SE
344 string_t s,d;
345 s=ipaddr_to_string(source);
346 d=ipaddr_to_string(dest);
347 Message(M_ERR,"%s: don't know where to deliver packet "
348 "(s=%s, d=%s)\n", st->name, s, d);
349 free(s); free(d);
70dc107b
SE
350 netlink_icmp_simple(st,buf,client,3,0);
351 BUF_FREE(buf);
2fe58dfd 352 }
469fd1d9
SE
353 } else {
354 if (!allow_route &&
d3fe100d 355 !(st->routes[best_match]->options&OPT_ALLOWROUTE)) {
469fd1d9
SE
356 string_t s,d;
357 s=ipaddr_to_string(source);
358 d=ipaddr_to_string(dest);
359 /* We have a usable route but aren't allowed to use it.
360 Generate ICMP destination unreachable: communication
361 with destination network administratively prohibited */
362 Message(M_NOTICE,"%s: denied forwarding for packet (s=%s, d=%s)\n",
363 st->name,s,d);
364 free(s); free(d);
365
366 netlink_icmp_simple(st,buf,client,3,9);
367 BUF_FREE(buf);
368 }
369 if (best_quality>0) {
d3fe100d
SE
370 /* XXX Fragment if required */
371 st->routes[best_match]->deliver(
372 st->routes[best_match]->dst, buf);
373 st->routes[best_match]->outcount++;
469fd1d9
SE
374 BUF_ASSERT_FREE(buf);
375 } else {
376 /* Generate ICMP destination unreachable */
377 netlink_icmp_simple(st,buf,client,3,0); /* client==NULL */
378 BUF_FREE(buf);
379 }
2fe58dfd 380 }
70dc107b 381 BUF_ASSERT_FREE(buf);
4efd681a
SE
382}
383
70dc107b
SE
384static void netlink_packet_forward(struct netlink *st,
385 struct netlink_client *client,
386 struct buffer_if *buf)
4efd681a
SE
387{
388 struct iphdr *iph=(struct iphdr *)buf->start;
389
390 BUF_ASSERT_USED(buf);
391
392 /* Packet has already been checked */
393 if (iph->ttl<=1) {
394 /* Generate ICMP time exceeded */
70dc107b 395 netlink_icmp_simple(st,buf,client,11,0);
4efd681a
SE
396 BUF_FREE(buf);
397 return;
398 }
399 iph->ttl--;
400 iph->check=0;
401 iph->check=ip_fast_csum((uint8_t *)iph,iph->ihl);
402
70dc107b 403 netlink_packet_deliver(st,client,buf);
4efd681a
SE
404 BUF_ASSERT_FREE(buf);
405}
406
9d3a4132 407/* Deal with packets addressed explicitly to us */
70dc107b
SE
408static void netlink_packet_local(struct netlink *st,
409 struct netlink_client *client,
410 struct buffer_if *buf)
4efd681a
SE
411{
412 struct icmphdr *h;
413
469fd1d9
SE
414 st->localcount++;
415
4efd681a
SE
416 h=(struct icmphdr *)buf->start;
417
418 if ((ntohs(h->iph.frag_off)&0xbfff)!=0) {
9d3a4132
SE
419 Message(M_WARNING,"%s: fragmented packet addressed to secnet; "
420 "ignoring it\n",st->name);
4efd681a
SE
421 BUF_FREE(buf);
422 return;
423 }
424
425 if (h->iph.protocol==1) {
426 /* It's ICMP */
427 if (h->type==8 && h->code==0) {
428 /* ICMP echo-request. Special case: we re-use the buffer
429 to construct the reply. */
430 h->type=0;
431 h->iph.daddr=h->iph.saddr;
432 h->iph.saddr=htonl(st->secnet_address);
433 h->iph.ttl=255; /* Be nice and bump it up again... */
434 h->iph.check=0;
435 h->iph.check=ip_fast_csum((uint8_t *)h,h->iph.ihl);
436 netlink_icmp_csum(h);
70dc107b 437 netlink_packet_deliver(st,NULL,buf);
4efd681a
SE
438 return;
439 }
440 Message(M_WARNING,"%s: unknown incoming ICMP\n",st->name);
441 } else {
442 /* Send ICMP protocol unreachable */
70dc107b 443 netlink_icmp_simple(st,buf,client,3,2);
4efd681a
SE
444 BUF_FREE(buf);
445 return;
446 }
447
448 BUF_FREE(buf);
449}
450
9d3a4132
SE
451/* If cid==NULL packet is from host, otherwise cid specifies which tunnel
452 it came from. */
469fd1d9
SE
453static void netlink_incoming(struct netlink *st, struct netlink_client *client,
454 struct buffer_if *buf)
4efd681a 455{
4efd681a
SE
456 uint32_t source,dest;
457 struct iphdr *iph;
458
459 BUF_ASSERT_USED(buf);
460 if (!netlink_check(st,buf)) {
9d3a4132
SE
461 Message(M_WARNING,"%s: bad IP packet from %s\n",
462 st->name,client?client->name:"host");
4efd681a
SE
463 BUF_FREE(buf);
464 return;
465 }
466 iph=(struct iphdr *)buf->start;
467
468 source=ntohl(iph->saddr);
469 dest=ntohl(iph->daddr);
470
d3fe100d
SE
471 /* Check source. If we don't like the source, there's no point
472 generating ICMP because we won't know how to get it to the
473 source of the packet. */
9d3a4132 474 if (client) {
c6f79b17
SE
475 /* Check that the packet source is appropriate for the tunnel
476 it came down */
794f2398 477 if (!ipset_contains_addr(client->networks,source)) {
9d3a4132
SE
478 string_t s,d;
479 s=ipaddr_to_string(source);
480 d=ipaddr_to_string(dest);
481 Message(M_WARNING,"%s: packet from tunnel %s with bad "
482 "source address (s=%s,d=%s)\n",st->name,client->name,s,d);
483 free(s); free(d);
484 BUF_FREE(buf);
485 return;
486 }
487 } else {
c6f79b17
SE
488 /* Check that the packet originates in our configured local
489 network, and hasn't been forwarded from elsewhere or
490 generated with the wrong source address */
794f2398 491 if (!ipset_contains_addr(st->networks,source)) {
9d3a4132
SE
492 string_t s,d;
493 s=ipaddr_to_string(source);
494 d=ipaddr_to_string(dest);
495 Message(M_WARNING,"%s: outgoing packet with bad source address "
496 "(s=%s,d=%s)\n",st->name,s,d);
497 free(s); free(d);
498 BUF_FREE(buf);
499 return;
500 }
4efd681a 501 }
c6f79b17 502
794f2398
SE
503 /* If this is a point-to-point device we don't examine the
504 destination address at all; we blindly send it down our
505 one-and-only registered tunnel, or to the host, depending on
d3fe100d
SE
506 where it came from. It's up to external software to check
507 address validity and generate ICMP, etc. */
c6f79b17
SE
508 if (st->ptp) {
509 if (client) {
469fd1d9 510 st->deliver_to_host(st->dst,buf);
c6f79b17 511 } else {
469fd1d9 512 st->clients->deliver(st->clients->dst,buf);
c6f79b17
SE
513 }
514 BUF_ASSERT_FREE(buf);
515 return;
516 }
517
d3fe100d
SE
518 /* st->secnet_address needs checking before matching destination
519 addresses */
2fe58dfd 520 if (dest==st->secnet_address) {
9d3a4132 521 netlink_packet_local(st,client,buf);
4efd681a 522 BUF_ASSERT_FREE(buf);
2fe58dfd
SE
523 return;
524 }
70dc107b 525 netlink_packet_forward(st,client,buf);
4efd681a
SE
526 BUF_ASSERT_FREE(buf);
527}
528
469fd1d9
SE
529static void netlink_inst_incoming(void *sst, struct buffer_if *buf)
530{
531 struct netlink_client *c=sst;
532 struct netlink *st=c->nst;
533
534 netlink_incoming(st,c,buf);
535}
536
537static void netlink_dev_incoming(void *sst, struct buffer_if *buf)
538{
539 struct netlink *st=sst;
540
541 netlink_incoming(st,NULL,buf);
542}
543
d3fe100d 544static void netlink_set_quality(void *sst, uint32_t quality)
4efd681a 545{
d3fe100d
SE
546 struct netlink_client *c=sst;
547 struct netlink *st=c->nst;
4efd681a 548
d3fe100d
SE
549 c->link_quality=quality;
550 c->up=(c->link_quality==LINK_QUALITY_DOWN)?False:True;
551 if (c->options&OPT_SOFTROUTE) {
552 st->set_routes(st->dst,c);
4efd681a 553 }
4efd681a
SE
554}
555
d3fe100d
SE
556static void netlink_output_subnets(struct netlink *st, uint32_t loglevel,
557 struct subnet_list *snets)
4efd681a 558{
d3fe100d
SE
559 uint32_t i;
560 string_t net;
4efd681a 561
d3fe100d
SE
562 for (i=0; i<snets->entries; i++) {
563 net=subnet_to_string(snets->list[i]);
564 Message(loglevel,"%s ",net);
565 free(net);
9d3a4132 566 }
4efd681a
SE
567}
568
042a8da9 569static void netlink_dump_routes(struct netlink *st, bool_t requested)
9d3a4132
SE
570{
571 int i;
572 string_t net;
042a8da9 573 uint32_t c=M_INFO;
9d3a4132 574
042a8da9 575 if (requested) c=M_WARNING;
469fd1d9
SE
576 if (st->ptp) {
577 net=ipaddr_to_string(st->secnet_address);
578 Message(c,"%s: point-to-point (remote end is %s); routes:\n",
579 st->name, net);
9d3a4132 580 free(net);
d3fe100d 581 netlink_output_subnets(st,c,st->clients->subnets);
469fd1d9
SE
582 Message(c,"\n");
583 } else {
584 Message(c,"%s: routing table:\n",st->name);
d3fe100d
SE
585 for (i=0; i<st->n_clients; i++) {
586 netlink_output_subnets(st,c,st->routes[i]->subnets);
587 Message(c,"-> tunnel %s (%s,%s routes,%s,quality %d,use %d)\n",
588 st->routes[i]->name,
589 st->routes[i]->options&OPT_SOFTROUTE?"soft":"hard",
590 st->routes[i]->options&OPT_ALLOWROUTE?"free":"restricted",
591 st->routes[i]->up?"up":"down",
592 st->routes[i]->link_quality,
593 st->routes[i]->outcount);
469fd1d9
SE
594 }
595 net=ipaddr_to_string(st->secnet_address);
596 Message(c,"%s/32 -> netlink \"%s\" (use %d)\n",
597 net,st->name,st->localcount);
9d3a4132 598 free(net);
794f2398
SE
599 for (i=0; i<st->subnets->entries; i++) {
600 net=subnet_to_string(st->subnets->list[i]);
601 Message(c,"%s ",net);
469fd1d9
SE
602 free(net);
603 }
794f2398
SE
604 if (i>0)
605 Message(c,"-> host (use %d)\n",st->outcount);
9d3a4132
SE
606 }
607}
608
d3fe100d
SE
609/* ap is a pointer to a member of the routes array */
610static int netlink_compare_client_priority(const void *ap, const void *bp)
70dc107b 611{
d3fe100d
SE
612 const struct netlink_client *const*a=ap;
613 const struct netlink_client *const*b=bp;
70dc107b 614
d3fe100d
SE
615 if ((*a)->priority==(*b)->priority) return 0;
616 if ((*a)->priority<(*b)->priority) return 1;
70dc107b
SE
617 return -1;
618}
619
620static void netlink_phase_hook(void *sst, uint32_t new_phase)
621{
622 struct netlink *st=sst;
623 struct netlink_client *c;
d3fe100d 624 uint32_t i;
70dc107b
SE
625
626 /* All the networks serviced by the various tunnels should now
627 * have been registered. We build a routing table by sorting the
d3fe100d
SE
628 * clients by priority. */
629 st->routes=safe_malloc(st->n_clients*sizeof(*st->routes),
70dc107b
SE
630 "netlink_phase_hook");
631 /* Fill the table */
632 i=0;
d3fe100d
SE
633 for (c=st->clients; c; c=c->next)
634 st->routes[i++]=c;
635 /* Sort the table in descending order of priority */
636 qsort(st->routes,st->n_clients,sizeof(*st->routes),
637 netlink_compare_client_priority);
9d3a4132 638
042a8da9
SE
639 netlink_dump_routes(st,False);
640}
641
642static void netlink_signal_handler(void *sst, int signum)
643{
644 struct netlink *st=sst;
645 Message(M_INFO,"%s: route dump requested by SIGUSR1\n",st->name);
646 netlink_dump_routes(st,True);
70dc107b
SE
647}
648
794f2398
SE
649static void netlink_inst_output_config(void *sst, struct buffer_if *buf)
650{
651/* struct netlink_client *c=sst; */
652/* struct netlink *st=c->nst; */
653
654 /* For now we don't output anything */
655 BUF_ASSERT_USED(buf);
656}
657
658static bool_t netlink_inst_check_config(void *sst, struct buffer_if *buf)
659{
660/* struct netlink_client *c=sst; */
661/* struct netlink *st=c->nst; */
662
663 BUF_ASSERT_USED(buf);
664 /* We need to eat all of the configuration information from the buffer
665 for backward compatibility. */
666 buf->size=0;
667 return True;
668}
669
d3fe100d
SE
670static void netlink_inst_set_mtu(void *sst, uint32_t new_mtu)
671{
672 struct netlink_client *c=sst;
673
674 c->mtu=new_mtu;
675}
676
469fd1d9
SE
677static void netlink_inst_reg(void *sst, netlink_deliver_fn *deliver,
678 void *dst, uint32_t max_start_pad,
679 uint32_t max_end_pad)
680{
681 struct netlink_client *c=sst;
682 struct netlink *st=c->nst;
683
684 if (max_start_pad > st->max_start_pad) st->max_start_pad=max_start_pad;
685 if (max_end_pad > st->max_end_pad) st->max_end_pad=max_end_pad;
686 c->deliver=deliver;
687 c->dst=dst;
688}
689
690static struct flagstr netlink_option_table[]={
691 { "soft", OPT_SOFTROUTE },
692 { "allow-route", OPT_ALLOWROUTE },
693 { NULL, 0}
694};
695/* This is the routine that gets called when the closure that's
696 returned by an invocation of a netlink device closure (eg. tun,
697 userv-ipif) is invoked. It's used to create routes and pass in
698 information about them; the closure it returns is used by site
699 code. */
700static closure_t *netlink_inst_create(struct netlink *st,
701 struct cloc loc, dict_t *dict)
702{
703 struct netlink_client *c;
704 string_t name;
794f2398 705 struct ipset *networks;
d3fe100d 706 uint32_t options,priority,mtu;
794f2398 707 list_t *l;
469fd1d9
SE
708
709 name=dict_read_string(dict, "name", True, st->name, loc);
710
794f2398
SE
711 l=dict_lookup(dict,"routes");
712 if (!l)
713 cfgfatal(loc,st->name,"required parameter \"routes\" not found\n");
714 networks=string_list_to_ipset(l,loc,st->name,"routes");
469fd1d9
SE
715 options=string_list_to_word(dict_lookup(dict,"options"),
716 netlink_option_table,st->name);
717
d3fe100d
SE
718 priority=dict_read_number(dict,"priority",False,st->name,loc,0);
719 mtu=dict_read_number(dict,"mtu",False,st->name,loc,0);
720
721 if ((options&OPT_SOFTROUTE) && !st->set_routes) {
469fd1d9
SE
722 cfgfatal(loc,st->name,"this netlink device does not support "
723 "soft routes.\n");
724 return NULL;
725 }
726
727 if (options&OPT_SOFTROUTE) {
728 /* XXX for now we assume that soft routes require root privilege;
729 this may not always be true. The device driver can tell us. */
730 require_root_privileges=True;
731 require_root_privileges_explanation="netlink: soft routes";
732 if (st->ptp) {
733 cfgfatal(loc,st->name,"point-to-point netlinks do not support "
734 "soft routes.\n");
735 return NULL;
736 }
737 }
738
794f2398
SE
739 /* Check that nets are a subset of st->remote_networks;
740 refuse to register if they are not. */
741 if (!ipset_is_subset(st->remote_networks,networks)) {
742 cfgfatal(loc,st->name,"routes are not allowed\n");
469fd1d9
SE
743 return NULL;
744 }
745
746 c=safe_malloc(sizeof(*c),"netlink_inst_create");
747 c->cl.description=name;
748 c->cl.type=CL_NETLINK;
749 c->cl.apply=NULL;
750 c->cl.interface=&c->ops;
751 c->ops.st=c;
752 c->ops.reg=netlink_inst_reg;
753 c->ops.deliver=netlink_inst_incoming;
754 c->ops.set_quality=netlink_set_quality;
794f2398
SE
755 c->ops.output_config=netlink_inst_output_config;
756 c->ops.check_config=netlink_inst_check_config;
d3fe100d 757 c->ops.set_mtu=netlink_inst_set_mtu;
469fd1d9
SE
758 c->nst=st;
759
760 c->networks=networks;
794f2398 761 c->subnets=ipset_to_subnet_list(networks);
d3fe100d 762 c->priority=priority;
469fd1d9
SE
763 c->deliver=NULL;
764 c->dst=NULL;
765 c->name=name;
469fd1d9 766 c->link_quality=LINK_QUALITY_DOWN;
d3fe100d
SE
767 c->mtu=mtu?mtu:st->mtu;
768 c->options=options;
769 c->outcount=0;
770 c->up=False;
771 c->kup=False;
469fd1d9
SE
772 c->next=st->clients;
773 st->clients=c;
d3fe100d 774 st->n_clients++;
469fd1d9
SE
775
776 return &c->cl;
777}
778
779static list_t *netlink_inst_apply(closure_t *self, struct cloc loc,
780 dict_t *context, list_t *args)
781{
782 struct netlink *st=self->interface;
783
784 dict_t *dict;
785 item_t *item;
786 closure_t *cl;
787
469fd1d9
SE
788 item=list_elem(args,0);
789 if (!item || item->type!=t_dict) {
790 cfgfatal(loc,st->name,"must have a dictionary argument\n");
791 }
792 dict=item->data.dict;
793
794 cl=netlink_inst_create(st,loc,dict);
795
796 return new_closure(cl);
797}
798
9d3a4132
SE
799netlink_deliver_fn *netlink_init(struct netlink *st,
800 void *dst, struct cloc loc,
801 dict_t *dict, string_t description,
d3fe100d 802 netlink_route_fn *set_routes,
9d3a4132 803 netlink_deliver_fn *to_host)
4efd681a 804{
c6f79b17 805 item_t *sa, *ptpa;
794f2398 806 list_t *l;
c6f79b17 807
4efd681a
SE
808 st->dst=dst;
809 st->cl.description=description;
469fd1d9
SE
810 st->cl.type=CL_PURE;
811 st->cl.apply=netlink_inst_apply;
812 st->cl.interface=st;
4efd681a
SE
813 st->max_start_pad=0;
814 st->max_end_pad=0;
815 st->clients=NULL;
d3fe100d
SE
816 st->routes=NULL;
817 st->n_clients=0;
818 st->set_routes=set_routes;
4efd681a
SE
819 st->deliver_to_host=to_host;
820
794f2398 821 st->name=dict_read_string(dict,"name",False,description,loc);
4efd681a 822 if (!st->name) st->name=description;
794f2398
SE
823 l=dict_lookup(dict,"networks");
824 if (l)
825 st->networks=string_list_to_ipset(l,loc,st->name,"networks");
826 else {
827 Message(M_WARNING,"%s: no local networks (parameter \"networks\") "
828 "defined\n",st->name);
829 st->networks=ipset_new();
830 }
831 l=dict_lookup(dict,"remote-networks");
832 if (l) {
833 st->remote_networks=string_list_to_ipset(l,loc,st->name,
834 "remote-networks");
835 } else {
836 struct ipset *empty;
837 empty=ipset_new();
838 st->remote_networks=ipset_complement(empty);
839 ipset_free(empty);
840 }
841
c6f79b17 842 sa=dict_find_item(dict,"secnet-address",False,"netlink",loc);
469fd1d9 843 ptpa=dict_find_item(dict,"ptp-address",False,"netlink",loc);
c6f79b17
SE
844 if (sa && ptpa) {
845 cfgfatal(loc,st->name,"you may not specify secnet-address and "
846 "ptp-address in the same netlink device\n");
847 }
848 if (!(sa || ptpa)) {
849 cfgfatal(loc,st->name,"you must specify secnet-address or "
850 "ptp-address for this netlink device\n");
851 }
852 if (sa) {
794f2398 853 st->secnet_address=string_item_to_ipaddr(sa,"netlink");
c6f79b17
SE
854 st->ptp=False;
855 } else {
794f2398 856 st->secnet_address=string_item_to_ipaddr(ptpa,"netlink");
c6f79b17
SE
857 st->ptp=True;
858 }
d3fe100d
SE
859 /* To be strictly correct we could subtract secnet_address from
860 networks here. It shouldn't make any practical difference,
794f2398
SE
861 though, and will make the route dump look complicated... */
862 st->subnets=ipset_to_subnet_list(st->networks);
4efd681a
SE
863 st->mtu=dict_read_number(dict, "mtu", False, "netlink", loc, DEFAULT_MTU);
864 buffer_new(&st->icmp,ICMP_BUFSIZE);
469fd1d9
SE
865 st->outcount=0;
866 st->localcount=0;
70dc107b
SE
867
868 add_hook(PHASE_SETUP,netlink_phase_hook,st);
042a8da9 869 request_signal_notification(SIGUSR1, netlink_signal_handler, st);
4efd681a 870
469fd1d9
SE
871 /* If we're point-to-point then we return a CL_NETLINK directly,
872 rather than a CL_NETLINK_OLD or pure closure (depending on
873 compatibility). This CL_NETLINK is for our one and only
874 client. Our cl.apply function is NULL. */
875 if (st->ptp) {
876 closure_t *cl;
877 cl=netlink_inst_create(st,loc,dict);
878 st->cl=*cl;
879 }
880 return netlink_dev_incoming;
2fe58dfd
SE
881}
882
9d3a4132 883/* No connection to the kernel at all... */
2fe58dfd 884
9d3a4132 885struct null {
4efd681a 886 struct netlink nl;
4efd681a 887};
2fe58dfd 888
d3fe100d 889static bool_t null_set_route(void *sst, struct netlink_client *routes)
4efd681a 890{
9d3a4132 891 struct null *st=sst;
d3fe100d
SE
892
893 if (routes->up!=routes->kup) {
894 Message(M_INFO,"%s: setting routes for tunnel %s to state %s\n",
895 st->nl.name,routes->name,
896 routes->up?"up":"down");
897 routes->kup=routes->up;
9d3a4132 898 return True;
2fe58dfd 899 }
9d3a4132 900 return False;
2fe58dfd 901}
9d3a4132 902
469fd1d9 903static void null_deliver(void *sst, struct buffer_if *buf)
2fe58dfd
SE
904{
905 return;
906}
907
908static list_t *null_apply(closure_t *self, struct cloc loc, dict_t *context,
909 list_t *args)
910{
911 struct null *st;
4efd681a
SE
912 item_t *item;
913 dict_t *dict;
2fe58dfd 914
4efd681a 915 st=safe_malloc(sizeof(*st),"null_apply");
2fe58dfd 916
4efd681a
SE
917 item=list_elem(args,0);
918 if (!item || item->type!=t_dict)
919 cfgfatal(loc,"null-netlink","parameter must be a dictionary\n");
920
921 dict=item->data.dict;
922
9d3a4132
SE
923 netlink_init(&st->nl,st,loc,dict,"null-netlink",null_set_route,
924 null_deliver);
4efd681a
SE
925
926 return new_closure(&st->nl.cl);
2fe58dfd
SE
927}
928
929init_module netlink_module;
930void netlink_module(dict_t *dict)
931{
4efd681a 932 add_closure(dict,"null-netlink",null_apply);
2fe58dfd 933}