This source file includes following definitions.
- ip_loopback
- ip_send
- ip_send_room
- ip_build_header
- ip_send_check
- ip_queue_xmit
- ip_build_xmit
- ip_netlink_msg
- ip_rt_event
- ip_init
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 #include <asm/segment.h>
23 #include <asm/system.h>
24 #include <linux/types.h>
25 #include <linux/kernel.h>
26 #include <linux/sched.h>
27 #include <linux/mm.h>
28 #include <linux/string.h>
29 #include <linux/errno.h>
30 #include <linux/config.h>
31
32 #include <linux/socket.h>
33 #include <linux/sockios.h>
34 #include <linux/in.h>
35 #include <linux/inet.h>
36 #include <linux/netdevice.h>
37 #include <linux/etherdevice.h>
38 #include <linux/proc_fs.h>
39 #include <linux/stat.h>
40
41 #include <net/snmp.h>
42 #include <net/ip.h>
43 #include <net/protocol.h>
44 #include <net/route.h>
45 #include <net/tcp.h>
46 #include <net/udp.h>
47 #include <linux/skbuff.h>
48 #include <net/sock.h>
49 #include <net/arp.h>
50 #include <net/icmp.h>
51 #include <net/raw.h>
52 #include <net/checksum.h>
53 #include <linux/igmp.h>
54 #include <linux/ip_fw.h>
55 #include <linux/firewall.h>
56 #include <linux/mroute.h>
57 #include <net/netlink.h>
58
59
60
61
62
63 static void ip_loopback(struct device *old_dev, struct sk_buff *skb)
64 {
65 struct device *dev=&loopback_dev;
66 int len=ntohs(skb->ip_hdr->tot_len);
67 struct sk_buff *newskb=dev_alloc_skb(len+dev->hard_header_len+15);
68
69 if(newskb==NULL)
70 return;
71
72 newskb->link3=NULL;
73 newskb->sk=NULL;
74 newskb->dev=dev;
75 newskb->saddr=skb->saddr;
76 newskb->daddr=skb->daddr;
77 newskb->raddr=skb->raddr;
78 newskb->free=1;
79 newskb->lock=0;
80 newskb->users=0;
81 newskb->pkt_type=skb->pkt_type;
82
83
84
85
86 ip_send(newskb, skb->ip_hdr->daddr, len, dev, skb->ip_hdr->saddr);
87
88
89
90 newskb->ip_hdr=(struct iphdr *)skb_put(newskb, len);
91 memcpy(newskb->proto_priv, skb->proto_priv, sizeof(skb->proto_priv));
92
93
94
95
96 memcpy(newskb->ip_hdr,skb->ip_hdr,len);
97
98
99
100
101 ip_queue_xmit(NULL, dev, newskb, 1);
102 }
103
104
105
106
107
108
109
110 int ip_send(struct sk_buff *skb, __u32 daddr, int len, struct device *dev, __u32 saddr)
111 {
112 int mac = 0;
113
114 skb->dev = dev;
115 skb->arp = 1;
116 if (dev->hard_header)
117 {
118
119
120
121
122 skb_reserve(skb,(dev->hard_header_len+15)&~15);
123 mac = dev->hard_header(skb, dev, ETH_P_IP, NULL, NULL, len);
124 if (mac < 0)
125 {
126 mac = -mac;
127 skb->arp = 0;
128 skb->raddr = daddr;
129 }
130 }
131 return mac;
132 }
133
134 static int ip_send_room(struct sk_buff *skb, __u32 daddr, int len, struct device *dev, __u32 saddr)
135 {
136 int mac = 0;
137
138 skb->dev = dev;
139 skb->arp = 1;
140 if (dev->hard_header)
141 {
142 skb_reserve(skb,MAX_HEADER);
143 mac = dev->hard_header(skb, dev, ETH_P_IP, NULL, NULL, len);
144 if (mac < 0)
145 {
146 mac = -mac;
147 skb->arp = 0;
148 skb->raddr = daddr;
149 }
150 }
151 return mac;
152 }
153
154 int ip_id_count = 0;
155
156
157
158
159
160
161
162 int ip_build_header(struct sk_buff *skb, __u32 saddr, __u32 daddr,
163 struct device **dev, int type, struct options *opt, int len, int tos, int ttl)
164 {
165 struct rtable *rt;
166 __u32 raddr;
167 int tmp;
168 __u32 src;
169 struct iphdr *iph;
170 __u32 final_daddr = daddr;
171
172 if (opt && opt->srr)
173 daddr = opt->faddr;
174
175
176
177
178
179 #ifdef CONFIG_IP_MULTICAST
180 if(MULTICAST(daddr) && *dev==NULL && skb->sk && *skb->sk->ip_mc_name)
181 *dev=dev_get(skb->sk->ip_mc_name);
182 #endif
183 if (*dev == NULL)
184 {
185 if(skb->localroute)
186 rt = ip_rt_local(daddr, NULL, &src);
187 else
188 rt = ip_rt_route(daddr, NULL, &src);
189 if (rt == NULL)
190 {
191 ip_statistics.IpOutNoRoutes++;
192 return(-ENETUNREACH);
193 }
194
195 *dev = rt->rt_dev;
196
197
198
199
200 if (LOOPBACK(saddr) && !LOOPBACK(daddr))
201 saddr = src;
202 raddr = rt->rt_gateway;
203
204 }
205 else
206 {
207
208
209
210 if(skb->localroute)
211 rt = ip_rt_local(daddr, NULL, &src);
212 else
213 rt = ip_rt_route(daddr, NULL, &src);
214
215
216
217
218 if (LOOPBACK(saddr) && !LOOPBACK(daddr))
219 saddr = src;
220
221 raddr = (rt == NULL) ? 0 : rt->rt_gateway;
222 }
223
224
225
226
227 if (saddr == 0)
228 saddr = src;
229
230
231
232
233 if (raddr == 0)
234 raddr = daddr;
235
236
237
238
239
240 if(type==IPPROTO_TCP)
241 tmp = ip_send_room(skb, raddr, len, *dev, saddr);
242 else
243 tmp = ip_send(skb, raddr, len, *dev, saddr);
244
245
246
247
248
249 skb->dev = *dev;
250 skb->saddr = saddr;
251
252
253
254
255
256
257
258
259
260
261 if(type == IPPROTO_RAW)
262 return (tmp);
263
264
265
266
267
268 if (opt)
269 iph=(struct iphdr *)skb_put(skb,sizeof(struct iphdr) + opt->optlen);
270 else
271 iph=(struct iphdr *)skb_put(skb,sizeof(struct iphdr));
272
273 iph->version = 4;
274 iph->ihl = 5;
275 iph->tos = tos;
276 iph->frag_off = 0;
277 iph->ttl = ttl;
278 iph->daddr = daddr;
279 iph->saddr = saddr;
280 iph->protocol = type;
281 skb->ip_hdr = iph;
282
283 if (!opt || !opt->optlen)
284 return sizeof(struct iphdr) + tmp;
285 if (opt->is_strictroute && rt && rt->rt_gateway)
286 {
287 ip_statistics.IpOutNoRoutes++;
288 return -ENETUNREACH;
289 }
290 iph->ihl += opt->optlen>>2;
291 ip_options_build(skb, opt, final_daddr, (*dev)->pa_addr, 0);
292 return iph->ihl*4 + tmp;
293 }
294
295
296
297
298
299
300 void ip_send_check(struct iphdr *iph)
301 {
302 iph->check = 0;
303 iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
304 }
305
306
307
308
309
310
311
312
313
314
315 void ip_queue_xmit(struct sock *sk, struct device *dev,
316 struct sk_buff *skb, int free)
317 {
318 struct iphdr *iph;
319
320
321
322 if (dev == NULL)
323 {
324 NETDEBUG(printk("IP: ip_queue_xmit dev = NULL\n"));
325 return;
326 }
327
328 IS_SKB(skb);
329
330
331
332
333
334
335 skb->dev = dev;
336 skb->when = jiffies;
337
338
339
340
341
342
343
344
345
346 iph = skb->ip_hdr;
347 iph->tot_len = ntohs(skb->len-(((unsigned char *)iph)-skb->data));
348
349 #ifdef CONFIG_FIREWALL
350 if(call_out_firewall(PF_INET, skb, iph) < FW_ACCEPT)
351
352 return;
353 #endif
354
355
356
357
358
359 if(free!=2)
360 iph->id = htons(ip_id_count++);
361 else
362 free=1;
363
364
365 if (sk == NULL)
366 free = 1;
367
368 skb->free = free;
369
370
371
372
373
374
375
376 if(ntohs(iph->tot_len)> dev->mtu)
377 {
378 ip_fragment(sk,skb,dev,0);
379 IS_SKB(skb);
380 kfree_skb(skb,FREE_WRITE);
381 return;
382 }
383
384
385
386
387
388 ip_send_check(iph);
389
390
391
392
393
394
395
396
397
398 if (skb->next != NULL)
399 {
400 NETDEBUG(printk("ip_queue_xmit: next != NULL\n"));
401 skb_unlink(skb);
402 }
403
404
405
406
407
408
409
410
411 if (!free)
412 {
413 unsigned long flags;
414
415
416 sk->packets_out++;
417
418
419 save_flags(flags);
420 cli();
421
422 if (skb->link3 != NULL)
423 {
424 NETDEBUG(printk("ip.c: link3 != NULL\n"));
425 skb->link3 = NULL;
426 }
427 if (sk->send_head == NULL)
428 {
429 sk->send_tail = skb;
430 sk->send_head = skb;
431 }
432 else
433 {
434 sk->send_tail->link3 = skb;
435 sk->send_tail = skb;
436 }
437
438
439
440 restore_flags(flags);
441 }
442 else
443
444 skb->sk = sk;
445
446
447
448
449
450 ip_statistics.IpOutRequests++;
451 #ifdef CONFIG_IP_ACCT
452 ip_fw_chk(iph,dev,ip_acct_chain,IP_FW_F_ACCEPT,1);
453 #endif
454
455 #ifdef CONFIG_IP_MULTICAST
456
457
458
459
460
461 if (MULTICAST(iph->daddr) && !(dev->flags&IFF_LOOPBACK))
462 {
463 if(sk==NULL || sk->ip_mc_loop)
464 {
465 if(iph->daddr==IGMP_ALL_HOSTS || (dev->flags&IFF_ALLMULTI))
466 {
467 ip_loopback(dev,skb);
468 }
469 else
470 {
471 struct ip_mc_list *imc=dev->ip_mc_list;
472 while(imc!=NULL)
473 {
474 if(imc->multiaddr==iph->daddr)
475 {
476 ip_loopback(dev,skb);
477 break;
478 }
479 imc=imc->next;
480 }
481 }
482 }
483
484
485 if(skb->ip_hdr->ttl==0)
486 {
487 kfree_skb(skb, FREE_READ);
488 return;
489 }
490 }
491 #endif
492 if((dev->flags&IFF_BROADCAST) && (iph->daddr==dev->pa_brdaddr||iph->daddr==0xFFFFFFFF) && !(dev->flags&IFF_LOOPBACK))
493 ip_loopback(dev,skb);
494
495 if (dev->flags & IFF_UP)
496 {
497
498
499
500
501
502 if (sk != NULL)
503 {
504 dev_queue_xmit(skb, dev, sk->priority);
505 }
506 else
507 {
508 dev_queue_xmit(skb, dev, SOPRI_NORMAL);
509 }
510 }
511 else
512 {
513 if(sk)
514 sk->err = ENETDOWN;
515 ip_statistics.IpOutDiscards++;
516 if (free)
517 kfree_skb(skb, FREE_WRITE);
518 }
519 }
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542 int ip_build_xmit(struct sock *sk,
543 void getfrag (const void *,
544 __u32,
545 char *,
546 unsigned int,
547 unsigned int),
548 const void *frag,
549 unsigned short int length,
550 __u32 daddr,
551 __u32 user_saddr,
552 struct options * opt,
553 int flags,
554 int type)
555 {
556 struct rtable *rt;
557 unsigned int fraglen, maxfraglen, fragheaderlen;
558 int offset, mf;
559 __u32 saddr;
560 unsigned short id;
561 struct iphdr *iph;
562 int local=0;
563 struct device *dev;
564 int nfrags=0;
565 __u32 true_daddr = daddr;
566
567 if (opt && opt->srr && !sk->ip_hdrincl)
568 daddr = opt->faddr;
569
570 ip_statistics.IpOutRequests++;
571
572 #ifdef CONFIG_IP_MULTICAST
573 if(sk && MULTICAST(daddr) && *sk->ip_mc_name)
574 {
575 dev=dev_get(sk->ip_mc_name);
576 if(!dev)
577 return -ENODEV;
578 rt=NULL;
579 if (sk->saddr && (!LOOPBACK(sk->saddr) || LOOPBACK(daddr)))
580 saddr = sk->saddr;
581 else
582 saddr = dev->pa_addr;
583 }
584 else
585 {
586 #endif
587
588
589
590
591 if(sk->localroute || flags&MSG_DONTROUTE)
592 local=1;
593
594 rt = sk->ip_route_cache;
595
596
597
598
599
600
601 saddr=sk->ip_route_saddr;
602 if(!rt || sk->ip_route_stamp != rt_stamp ||
603 daddr!=sk->ip_route_daddr || sk->ip_route_local!=local ||
604 (sk->saddr && sk->saddr != saddr))
605 {
606 if(local)
607 rt = ip_rt_local(daddr, NULL, &saddr);
608 else
609 rt = ip_rt_route(daddr, NULL, &saddr);
610 sk->ip_route_local=local;
611 sk->ip_route_daddr=daddr;
612 sk->ip_route_saddr=saddr;
613 sk->ip_route_stamp=rt_stamp;
614 sk->ip_route_cache=rt;
615 sk->ip_hcache_ver=NULL;
616 sk->ip_hcache_state= 0;
617 }
618 else if(rt)
619 {
620
621
622
623
624
625
626 if(rt->rt_dev->header_cache && sk->ip_hcache_state!= -1)
627 {
628 if(sk->ip_hcache_ver==NULL || sk->ip_hcache_stamp!=*sk->ip_hcache_ver)
629 rt->rt_dev->header_cache(rt->rt_dev,sk,saddr,daddr);
630 else
631
632 sk->ip_hcache_state= -1;
633 }
634 }
635
636 if (rt == NULL)
637 {
638 ip_statistics.IpOutNoRoutes++;
639 return(-ENETUNREACH);
640 }
641
642 if (sk->saddr && (!LOOPBACK(sk->saddr) || LOOPBACK(daddr)))
643 saddr = sk->saddr;
644
645 dev=rt->rt_dev;
646 #ifdef CONFIG_IP_MULTICAST
647 }
648 #endif
649 if (user_saddr)
650 saddr = user_saddr;
651
652
653
654
655
656
657
658
659
660
661 length += 20;
662 if (!sk->ip_hdrincl && opt)
663 {
664 length += opt->optlen;
665 if (opt->is_strictroute && rt && rt->rt_gateway)
666 {
667 ip_statistics.IpOutNoRoutes++;
668 return -ENETUNREACH;
669 }
670 }
671 if(length <= dev->mtu && !MULTICAST(daddr) && daddr!=0xFFFFFFFF && daddr!=dev->pa_brdaddr)
672 {
673 int error;
674 struct sk_buff *skb=sock_alloc_send_skb(sk, length+15+dev->hard_header_len,0, 0,&error);
675 if(skb==NULL)
676 {
677 ip_statistics.IpOutDiscards++;
678 return error;
679 }
680 skb->dev=dev;
681 skb->free=1;
682 skb->when=jiffies;
683 skb->sk=sk;
684 skb->arp=0;
685 skb->saddr=saddr;
686 skb->raddr=(rt&&rt->rt_gateway)?rt->rt_gateway:daddr;
687 skb_reserve(skb,(dev->hard_header_len+15)&~15);
688 if(sk->ip_hcache_state>0)
689 {
690 memcpy(skb_push(skb,dev->hard_header_len),sk->ip_hcache_data,dev->hard_header_len);
691 skb->arp=1;
692 }
693 else if(dev->hard_header)
694 {
695 if(dev->hard_header(skb,dev,ETH_P_IP,NULL,NULL,0)>0)
696 skb->arp=1;
697 }
698 else
699 skb->arp=1;
700 skb->ip_hdr=iph=(struct iphdr *)skb_put(skb,length);
701 dev_lock_list();
702 if(!sk->ip_hdrincl)
703 {
704 iph->version=4;
705 iph->ihl=5;
706 iph->tos=sk->ip_tos;
707 iph->tot_len = htons(length);
708 iph->id=htons(ip_id_count++);
709 iph->frag_off = 0;
710 iph->ttl=sk->ip_ttl;
711 iph->protocol=type;
712 iph->saddr=saddr;
713 iph->daddr=daddr;
714 if (opt)
715 {
716 iph->ihl += opt->optlen>>2;
717 ip_options_build(skb, opt,
718 true_daddr, dev->pa_addr, 0);
719 }
720 iph->check=0;
721 iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
722 getfrag(frag,saddr,((char *)iph)+iph->ihl*4,0, length-iph->ihl*4);
723 }
724 else
725 getfrag(frag,saddr,(void *)iph,0,length-20);
726 dev_unlock_list();
727 #ifdef CONFIG_FIREWALL
728 if(call_out_firewall(PF_INET, skb, iph)< FW_ACCEPT)
729 {
730 kfree_skb(skb, FREE_WRITE);
731 return -EPERM;
732 }
733 #endif
734 #ifdef CONFIG_IP_ACCT
735 ip_fw_chk((void *)skb->data,dev,ip_acct_chain, IP_FW_F_ACCEPT,1);
736 #endif
737 if(dev->flags&IFF_UP)
738 dev_queue_xmit(skb,dev,sk->priority);
739 else
740 {
741 ip_statistics.IpOutDiscards++;
742 kfree_skb(skb, FREE_WRITE);
743 }
744 return 0;
745 }
746 length-=20;
747 if (sk && !sk->ip_hdrincl && opt)
748 {
749 length -= opt->optlen;
750 fragheaderlen = dev->hard_header_len + sizeof(struct iphdr) + opt->optlen;
751 maxfraglen = ((dev->mtu-sizeof(struct iphdr)-opt->optlen) & ~7) + fragheaderlen;
752 }
753 else
754 {
755 fragheaderlen = dev->hard_header_len;
756 if(!sk->ip_hdrincl)
757 fragheaderlen += 20;
758
759
760
761
762
763
764 maxfraglen = ((dev->mtu-20) & ~7) + fragheaderlen;
765 }
766
767
768
769
770
771 offset = length - (length % (maxfraglen - fragheaderlen));
772
773
774
775
776
777 fraglen = length - offset + fragheaderlen;
778
779 if(length-offset==0)
780 {
781 fraglen = maxfraglen;
782 offset -= maxfraglen-fragheaderlen;
783 }
784
785
786
787
788
789
790 mf = 0;
791
792
793
794
795
796 if (sk->ip_hdrincl && offset > 0)
797 return(-EMSGSIZE);
798
799
800
801
802
803 dev_lock_list();
804
805
806
807
808
809 id = htons(ip_id_count++);
810
811
812
813
814
815 do
816 {
817 struct sk_buff * skb;
818 int error;
819 char *data;
820
821
822
823
824
825 skb = sock_alloc_send_skb(sk, fraglen+15, 0, 0, &error);
826 if (skb == NULL)
827 {
828 ip_statistics.IpOutDiscards++;
829 if(nfrags>1)
830 ip_statistics.IpFragCreates++;
831 dev_unlock_list();
832 return(error);
833 }
834
835
836
837
838
839 skb->next = skb->prev = NULL;
840 skb->dev = dev;
841 skb->when = jiffies;
842 skb->free = 1;
843 skb->sk = sk;
844 skb->arp = 0;
845 skb->saddr = saddr;
846 skb->raddr = (rt&&rt->rt_gateway) ? rt->rt_gateway : daddr;
847 skb_reserve(skb,(dev->hard_header_len+15)&~15);
848 data = skb_put(skb, fraglen-dev->hard_header_len);
849
850
851
852
853
854
855
856
857 if(sk->ip_hcache_state>0)
858 {
859 memcpy(skb_push(skb,dev->hard_header_len),sk->ip_hcache_data, dev->hard_header_len);
860 skb->arp=1;
861 }
862 else if (dev->hard_header)
863 {
864 if(dev->hard_header(skb, dev, ETH_P_IP,
865 NULL, NULL, 0)>0)
866 skb->arp=1;
867 }
868
869
870
871
872
873 skb->ip_hdr = iph = (struct iphdr *)data;
874
875
876
877
878
879 if(!sk->ip_hdrincl)
880 {
881
882 iph->version = 4;
883 iph->ihl = 5;
884 if (opt) {
885 iph->ihl += opt->optlen>>2;
886 ip_options_build(skb, opt,
887 true_daddr, dev->pa_addr, offset);
888 }
889 iph->tos = sk->ip_tos;
890 iph->tot_len = htons(fraglen - fragheaderlen + iph->ihl*4);
891 iph->id = id;
892 iph->frag_off = htons(offset>>3);
893 iph->frag_off |= mf;
894 #ifdef CONFIG_IP_MULTICAST
895 if (MULTICAST(daddr))
896 iph->ttl = sk->ip_mc_ttl;
897 else
898 #endif
899 iph->ttl = sk->ip_ttl;
900 iph->protocol = type;
901 iph->check = 0;
902 iph->saddr = saddr;
903 iph->daddr = daddr;
904 iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
905 data += iph->ihl*4;
906
907
908
909
910
911 mf = htons(IP_MF);
912 }
913
914
915
916
917
918 getfrag(frag, saddr, data, offset, fraglen-fragheaderlen);
919
920
921
922
923
924 #ifdef CONFIG_FIREWALL
925 if(!offset && call_out_firewall(PF_INET, skb, iph) < FW_ACCEPT)
926 {
927 kfree_skb(skb, FREE_WRITE);
928 dev_unlock_list();
929 return -EPERM;
930 }
931 #endif
932 #ifdef CONFIG_IP_ACCT
933 if(!offset)
934 ip_fw_chk(iph, dev, ip_acct_chain, IP_FW_F_ACCEPT, 1);
935 #endif
936 offset -= (maxfraglen-fragheaderlen);
937 fraglen = maxfraglen;
938
939 #ifdef CONFIG_IP_MULTICAST
940
941
942
943
944
945 if (MULTICAST(daddr) && !(dev->flags&IFF_LOOPBACK))
946 {
947
948
949
950
951
952
953
954 if(sk==NULL || sk->ip_mc_loop)
955 {
956 if(skb->daddr==IGMP_ALL_HOSTS || (dev->flags&IFF_ALLMULTI))
957 ip_loopback(rt?rt->rt_dev:dev,skb);
958 else
959 {
960 struct ip_mc_list *imc=rt?rt->rt_dev->ip_mc_list:dev->ip_mc_list;
961 while(imc!=NULL)
962 {
963 if(imc->multiaddr==daddr)
964 {
965 ip_loopback(rt?rt->rt_dev:dev,skb);
966 break;
967 }
968 imc=imc->next;
969 }
970 }
971 }
972
973
974
975
976
977
978 if(skb->ip_hdr->ttl==0)
979 kfree_skb(skb, FREE_READ);
980 }
981 #endif
982
983 nfrags++;
984
985
986
987
988
989 if((dev->flags&IFF_BROADCAST) && (daddr==0xFFFFFFFF || daddr==dev->pa_brdaddr) && !(dev->flags&IFF_LOOPBACK))
990 ip_loopback(dev,skb);
991
992
993
994
995
996 if (dev->flags & IFF_UP)
997 {
998 dev_queue_xmit(skb, dev, sk->priority);
999 }
1000 else
1001 {
1002
1003
1004
1005
1006 ip_statistics.IpOutDiscards++;
1007 if(nfrags>1)
1008 ip_statistics.IpFragCreates+=nfrags;
1009 kfree_skb(skb, FREE_WRITE);
1010 dev_unlock_list();
1011
1012
1013
1014 if(sk!=NULL)
1015 sk->err=ENETDOWN;
1016 return(0);
1017 }
1018 }
1019 while (offset >= 0);
1020 if(nfrags>1)
1021 ip_statistics.IpFragCreates+=nfrags;
1022 dev_unlock_list();
1023 return(0);
1024 }
1025
1026
1027
1028
1029
1030
1031 static struct packet_type ip_packet_type =
1032 {
1033 0,
1034 NULL,
1035 ip_rcv,
1036 NULL,
1037 NULL,
1038 };
1039
1040 #ifdef CONFIG_RTNETLINK
1041
1042
1043
1044
1045
1046 void ip_netlink_msg(unsigned long msg, __u32 daddr, __u32 gw, __u32 mask, short flags, short metric, char *name)
1047 {
1048 struct sk_buff *skb=alloc_skb(sizeof(struct netlink_rtinfo), GFP_ATOMIC);
1049 struct netlink_rtinfo *nrt;
1050 struct sockaddr_in *s;
1051 if(skb==NULL)
1052 return;
1053 nrt=(struct netlink_rtinfo *)skb_put(skb, sizeof(struct netlink_rtinfo));
1054 nrt->rtmsg_type=msg;
1055 s=(struct sockaddr_in *)&nrt->rtmsg_dst;
1056 s->sin_family=AF_INET;
1057 s->sin_addr.s_addr=daddr;
1058 s=(struct sockaddr_in *)&nrt->rtmsg_gateway;
1059 s->sin_family=AF_INET;
1060 s->sin_addr.s_addr=gw;
1061 s=(struct sockaddr_in *)&nrt->rtmsg_genmask;
1062 s->sin_family=AF_INET;
1063 s->sin_addr.s_addr=mask;
1064 nrt->rtmsg_flags=flags;
1065 nrt->rtmsg_metric=metric;
1066 strcpy(nrt->rtmsg_device,name);
1067 netlink_post(NETLINK_ROUTE, skb);
1068 }
1069
1070 #endif
1071
1072
1073
1074
1075
1076 static int ip_rt_event(unsigned long event, void *ptr)
1077 {
1078 struct device *dev=ptr;
1079 if(event==NETDEV_DOWN)
1080 {
1081 ip_netlink_msg(RTMSG_DELDEVICE, 0,0,0,0,0,dev->name);
1082 ip_rt_flush(dev);
1083 }
1084
1085
1086
1087 if(event==NETDEV_UP)
1088 {
1089 #ifdef CONFIG_IP_MULTICAST
1090 ip_mc_allhost(dev);
1091 #endif
1092 ip_netlink_msg(RTMSG_NEWDEVICE, 0,0,0,0,0,dev->name);
1093 }
1094 return NOTIFY_DONE;
1095 }
1096
1097 struct notifier_block ip_rt_notifier={
1098 ip_rt_event,
1099 NULL,
1100 0
1101 };
1102
1103
1104
1105
1106
1107 void ip_init(void)
1108 {
1109 ip_packet_type.type=htons(ETH_P_IP);
1110 dev_add_pack(&ip_packet_type);
1111
1112
1113 register_netdevice_notifier(&ip_rt_notifier);
1114
1115
1116
1117
1118
1119
1120 #ifdef CONFIG_IP_MULTICAST
1121 proc_net_register(&(struct proc_dir_entry) {
1122 PROC_NET_IGMP, 4, "igmp",
1123 S_IFREG | S_IRUGO, 1, 0, 0,
1124 0, &proc_net_inode_operations,
1125 ip_mc_procinfo
1126 });
1127 #endif
1128 }
1129