Deleted Added
full compact
in.c (50477) in.c (55009)
1/*
2 * Copyright (c) 1982, 1986, 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 17 unchanged lines hidden (view full) ---

26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * @(#)in.c 8.4 (Berkeley) 1/9/95
1/*
2 * Copyright (c) 1982, 1986, 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 17 unchanged lines hidden (view full) ---

26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * @(#)in.c 8.4 (Berkeley) 1/9/95
34 * $FreeBSD: head/sys/netinet/in.c 50477 1999-08-28 01:08:13Z peter $
34 * $FreeBSD: head/sys/netinet/in.c 55009 1999-12-22 19:13:38Z shin $
35 */
36
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/sockio.h>
40#include <sys/malloc.h>
41#include <sys/proc.h>
42#include <sys/socket.h>
43#include <sys/kernel.h>
44#include <sys/sysctl.h>
45
46#include <net/if.h>
35 */
36
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/sockio.h>
40#include <sys/malloc.h>
41#include <sys/proc.h>
42#include <sys/socket.h>
43#include <sys/kernel.h>
44#include <sys/sysctl.h>
45
46#include <net/if.h>
47#include <net/if_types.h>
47#include <net/route.h>
48
49#include <netinet/in.h>
50#include <netinet/in_var.h>
51
52#include <netinet/igmp_var.h>
53
48#include <net/route.h>
49
50#include <netinet/in.h>
51#include <netinet/in_var.h>
52
53#include <netinet/igmp_var.h>
54
55#include "gif.h"
56#if NGIF > 0
57#include <net/if_gif.h>
58#endif
59
54static MALLOC_DEFINE(M_IPMADDR, "in_multi", "internet multicast address");
55
60static MALLOC_DEFINE(M_IPMADDR, "in_multi", "internet multicast address");
61
62static int in_mask2len __P((struct in_addr *));
63static void in_len2mask __P((struct in_addr *, int));
64static int in_lifaddr_ioctl __P((struct socket *, u_long, caddr_t,
65 struct ifnet *, struct proc *));
66
56static void in_socktrim __P((struct sockaddr_in *));
57static int in_ifinit __P((struct ifnet *,
58 struct in_ifaddr *, struct sockaddr_in *, int));
59
60static int subnetsarelocal = 0;
61SYSCTL_INT(_net_inet_ip, OID_AUTO, subnets_are_local, CTLFLAG_RW,
62 &subnetsarelocal, 0, "");
63

--- 61 unchanged lines hidden (view full) ---

125 ap->sin_len = 0;
126 while (--cp >= cplim)
127 if (*cp) {
128 (ap)->sin_len = cp - (char *) (ap) + 1;
129 break;
130 }
131}
132
67static void in_socktrim __P((struct sockaddr_in *));
68static int in_ifinit __P((struct ifnet *,
69 struct in_ifaddr *, struct sockaddr_in *, int));
70
71static int subnetsarelocal = 0;
72SYSCTL_INT(_net_inet_ip, OID_AUTO, subnets_are_local, CTLFLAG_RW,
73 &subnetsarelocal, 0, "");
74

--- 61 unchanged lines hidden (view full) ---

136 ap->sin_len = 0;
137 while (--cp >= cplim)
138 if (*cp) {
139 (ap)->sin_len = cp - (char *) (ap) + 1;
140 break;
141 }
142}
143
144static int
145in_mask2len(mask)
146 struct in_addr *mask;
147{
148 int x, y;
149 u_char *p;
150
151 p = (u_char *)mask;
152 for (x = 0; x < sizeof(*mask); x++) {
153 if (p[x] != 0xff)
154 break;
155 }
156 y = 0;
157 if (x < sizeof(*mask)) {
158 for (y = 0; y < 8; y++) {
159 if ((p[x] & (0x80 >> y)) == 0)
160 break;
161 }
162 }
163 return x * 8 + y;
164}
165
166static void
167in_len2mask(mask, len)
168 struct in_addr *mask;
169 int len;
170{
171 int i;
172 u_char *p;
173
174 p = (u_char *)mask;
175 bzero(mask, sizeof(*mask));
176 for (i = 0; i < len / 8; i++)
177 p[i] = 0xff;
178 if (len % 8)
179 p[i] = (0xff00 >> (len % 8)) & 0xff;
180}
181
133static int in_interfaces; /* number of external internet interfaces */
134
135/*
136 * Generic internet control operations (ioctl's).
137 * Ifp is 0 if not an interface-specific ioctl.
138 */
139/* ARGSUSED */
140int

--- 8 unchanged lines hidden (view full) ---

149 register struct in_ifaddr *ia = 0, *iap;
150 register struct ifaddr *ifa;
151 struct in_ifaddr *oia;
152 struct in_aliasreq *ifra = (struct in_aliasreq *)data;
153 struct sockaddr_in oldaddr;
154 int error, hostIsNew, maskIsNew, s;
155 u_long i;
156
182static int in_interfaces; /* number of external internet interfaces */
183
184/*
185 * Generic internet control operations (ioctl's).
186 * Ifp is 0 if not an interface-specific ioctl.
187 */
188/* ARGSUSED */
189int

--- 8 unchanged lines hidden (view full) ---

198 register struct in_ifaddr *ia = 0, *iap;
199 register struct ifaddr *ifa;
200 struct in_ifaddr *oia;
201 struct in_aliasreq *ifra = (struct in_aliasreq *)data;
202 struct sockaddr_in oldaddr;
203 int error, hostIsNew, maskIsNew, s;
204 u_long i;
205
206#if NGIF > 0
207 if (ifp && ifp->if_type == IFT_GIF) {
208 switch (cmd) {
209 case SIOCSIFPHYADDR:
210 if (p &&
211 (error = suser(p)) != 0)
212 return(error);
213 case SIOCGIFPSRCADDR:
214 case SIOCGIFPDSTADDR:
215 return gif_ioctl(ifp, cmd, data);
216 }
217 }
218#endif
219
220 switch (cmd) {
221 case SIOCALIFADDR:
222 case SIOCDLIFADDR:
223 if (p && (error = suser(p)) != 0)
224 return error;
225 /*fall through*/
226 case SIOCGLIFADDR:
227 if (!ifp)
228 return EINVAL;
229 return in_lifaddr_ioctl(so, cmd, data, ifp, p);
230 }
231
157 /*
158 * Find address for this interface, if it exists.
159 *
160 * If an alias address was specified, find that one instead of
161 * the first one on the interface.
162 */
163 if (ifp)
164 for (iap = in_ifaddrhead.tqh_first; iap;

--- 194 unchanged lines hidden (view full) ---

359 if (ifp == 0 || ifp->if_ioctl == 0)
360 return (EOPNOTSUPP);
361 return ((*ifp->if_ioctl)(ifp, cmd, data));
362 }
363 return (0);
364}
365
366/*
232 /*
233 * Find address for this interface, if it exists.
234 *
235 * If an alias address was specified, find that one instead of
236 * the first one on the interface.
237 */
238 if (ifp)
239 for (iap = in_ifaddrhead.tqh_first; iap;

--- 194 unchanged lines hidden (view full) ---

434 if (ifp == 0 || ifp->if_ioctl == 0)
435 return (EOPNOTSUPP);
436 return ((*ifp->if_ioctl)(ifp, cmd, data));
437 }
438 return (0);
439}
440
441/*
442 * SIOC[GAD]LIFADDR.
443 * SIOCGLIFADDR: get first address. (?!?)
444 * SIOCGLIFADDR with IFLR_PREFIX:
445 * get first address that matches the specified prefix.
446 * SIOCALIFADDR: add the specified address.
447 * SIOCALIFADDR with IFLR_PREFIX:
448 * EINVAL since we can't deduce hostid part of the address.
449 * SIOCDLIFADDR: delete the specified address.
450 * SIOCDLIFADDR with IFLR_PREFIX:
451 * delete the first address that matches the specified prefix.
452 * return values:
453 * EINVAL on invalid parameters
454 * EADDRNOTAVAIL on prefix match failed/specified address not found
455 * other values may be returned from in_ioctl()
456 */
457static int
458in_lifaddr_ioctl(so, cmd, data, ifp, p)
459 struct socket *so;
460 u_long cmd;
461 caddr_t data;
462 struct ifnet *ifp;
463 struct proc *p;
464{
465 struct if_laddrreq *iflr = (struct if_laddrreq *)data;
466 struct ifaddr *ifa;
467
468 /* sanity checks */
469 if (!data || !ifp) {
470 panic("invalid argument to in_lifaddr_ioctl");
471 /*NOTRECHED*/
472 }
473
474 switch (cmd) {
475 case SIOCGLIFADDR:
476 /* address must be specified on GET with IFLR_PREFIX */
477 if ((iflr->flags & IFLR_PREFIX) == 0)
478 break;
479 /*FALLTHROUGH*/
480 case SIOCALIFADDR:
481 case SIOCDLIFADDR:
482 /* address must be specified on ADD and DELETE */
483 if (iflr->addr.__ss_family != AF_INET)
484 return EINVAL;
485 if (iflr->addr.__ss_len != sizeof(struct sockaddr_in))
486 return EINVAL;
487 /* XXX need improvement */
488 if (iflr->dstaddr.__ss_family
489 && iflr->dstaddr.__ss_family != AF_INET)
490 return EINVAL;
491 if (iflr->dstaddr.__ss_family
492 && iflr->dstaddr.__ss_len != sizeof(struct sockaddr_in))
493 return EINVAL;
494 break;
495 default: /*shouldn't happen*/
496 return EOPNOTSUPP;
497 }
498 if (sizeof(struct in_addr) * 8 < iflr->prefixlen)
499 return EINVAL;
500
501 switch (cmd) {
502 case SIOCALIFADDR:
503 {
504 struct in_aliasreq ifra;
505
506 if (iflr->flags & IFLR_PREFIX)
507 return EINVAL;
508
509 /* copy args to in_aliasreq, perform ioctl(SIOCAIFADDR_IN6). */
510 bzero(&ifra, sizeof(ifra));
511 bcopy(iflr->iflr_name, ifra.ifra_name,
512 sizeof(ifra.ifra_name));
513
514 bcopy(&iflr->addr, &ifra.ifra_addr, iflr->addr.__ss_len);
515
516 if (iflr->dstaddr.__ss_family) { /*XXX*/
517 bcopy(&iflr->dstaddr, &ifra.ifra_dstaddr,
518 iflr->dstaddr.__ss_len);
519 }
520
521 ifra.ifra_mask.sin_family = AF_INET;
522 ifra.ifra_mask.sin_len = sizeof(struct sockaddr_in);
523 in_len2mask(&ifra.ifra_mask.sin_addr, iflr->prefixlen);
524
525 return in_control(so, SIOCAIFADDR, (caddr_t)&ifra, ifp, p);
526 }
527 case SIOCGLIFADDR:
528 case SIOCDLIFADDR:
529 {
530 struct in_ifaddr *ia;
531 struct in_addr mask, candidate, match;
532 struct sockaddr_in *sin;
533 int cmp;
534
535 bzero(&mask, sizeof(mask));
536 if (iflr->flags & IFLR_PREFIX) {
537 /* lookup a prefix rather than address. */
538 in_len2mask(&mask, iflr->prefixlen);
539
540 sin = (struct sockaddr_in *)&iflr->addr;
541 match.s_addr = sin->sin_addr.s_addr;
542 match.s_addr &= mask.s_addr;
543
544 /* if you set extra bits, that's wrong */
545 if (match.s_addr != sin->sin_addr.s_addr)
546 return EINVAL;
547
548 cmp = 1;
549 } else {
550 if (cmd == SIOCGLIFADDR) {
551 /* on getting an address, take the 1st match */
552 cmp = 0; /*XXX*/
553 } else {
554 /* on deleting an address, do exact match */
555 in_len2mask(&mask, 32);
556 sin = (struct sockaddr_in *)&iflr->addr;
557 match.s_addr = sin->sin_addr.s_addr;
558
559 cmp = 1;
560 }
561 }
562
563 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
564 if (ifa->ifa_addr->sa_family != AF_INET6)
565 continue;
566 if (!cmp)
567 break;
568 candidate.s_addr = ((struct sockaddr_in *)&ifa->ifa_addr)->sin_addr.s_addr;
569 candidate.s_addr &= mask.s_addr;
570 if (candidate.s_addr == match.s_addr)
571 break;
572 }
573 if (!ifa)
574 return EADDRNOTAVAIL;
575 ia = (struct in_ifaddr *)ifa;
576
577 if (cmd == SIOCGLIFADDR) {
578 /* fill in the if_laddrreq structure */
579 bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin_len);
580
581 if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
582 bcopy(&ia->ia_dstaddr, &iflr->dstaddr,
583 ia->ia_dstaddr.sin_len);
584 } else
585 bzero(&iflr->dstaddr, sizeof(iflr->dstaddr));
586
587 iflr->prefixlen =
588 in_mask2len(&ia->ia_sockmask.sin_addr);
589
590 iflr->flags = 0; /*XXX*/
591
592 return 0;
593 } else {
594 struct in_aliasreq ifra;
595
596 /* fill in_aliasreq and do ioctl(SIOCDIFADDR_IN6) */
597 bzero(&ifra, sizeof(ifra));
598 bcopy(iflr->iflr_name, ifra.ifra_name,
599 sizeof(ifra.ifra_name));
600
601 bcopy(&ia->ia_addr, &ifra.ifra_addr,
602 ia->ia_addr.sin_len);
603 if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
604 bcopy(&ia->ia_dstaddr, &ifra.ifra_dstaddr,
605 ia->ia_dstaddr.sin_len);
606 }
607 bcopy(&ia->ia_sockmask, &ifra.ifra_dstaddr,
608 ia->ia_sockmask.sin_len);
609
610 return in_control(so, SIOCDIFADDR, (caddr_t)&ifra,
611 ifp, p);
612 }
613 }
614 }
615
616 return EOPNOTSUPP; /*just for safety*/
617}
618
619/*
367 * Delete any existing route for an interface.
368 */
369void
370in_ifscrub(ifp, ia)
371 register struct ifnet *ifp;
372 register struct in_ifaddr *ia;
373{
374

--- 226 unchanged lines hidden ---
620 * Delete any existing route for an interface.
621 */
622void
623in_ifscrub(ifp, ia)
624 register struct ifnet *ifp;
625 register struct in_ifaddr *ia;
626{
627

--- 226 unchanged lines hidden ---