xref: /original-bsd/sys/deprecated/bbnnet/in.c (revision c02e7ac7)
1 #ifdef	RCSIDENT
2 static char rcsident[] = "$Header: in.c,v 1.28 85/04/08 15:06:03 walsh Exp $";
3 #endif
4 
5 #include "../h/param.h"
6 #include "../h/mbuf.h"
7 #include "../h/protosw.h"
8 #include "../h/socket.h"
9 #include "../h/socketvar.h"
10 #include "../h/errno.h"
11 #include "../h/ioctl.h"
12 #include "../h/dir.h"
13 #include "../h/user.h"
14 
15 #include "../net/if.h"
16 #include "../net/route.h"
17 #include "../net/af.h"
18 #include "../net/netisr.h"
19 #include "../vax/mtpr.h"
20 
21 #include "../bbnnet/in.h"
22 #include "../bbnnet/net.h"
23 #include "../bbnnet/in_pcb.h"
24 #include "../bbnnet/in_var.h"
25 #include "../bbnnet/fsm.h"
26 #include "../bbnnet/tcp.h"
27 #include "../bbnnet/udp.h"
28 #include "../bbnnet/ip.h"
29 #include "../bbnnet/icmp.h"
30 
31 #ifdef BBNNET
32 
33 struct in_ifaddr *in_ifaddr;	/* list of Internet addresses for interfaces */
34 
35 #define	IN_CLASSA(i)		((((long)(i))&0x80000000)==0)
36 #define	IN_CLASSA_NET		0xff000000
37 #define	IN_CLASSA_NSHIFT	24
38 #define	IN_CLASSA_HOST		0x00ffffff
39 
40 #define	IN_CLASSB(i)		((((long)(i))&0xc0000000)==0x80000000)
41 #define	IN_CLASSB_NET		0xffff0000
42 #define	IN_CLASSB_NSHIFT	16
43 #define	IN_CLASSB_HOST		0x0000ffff
44 
45 #define	IN_CLASSC(i)		((((long)(i))&0xc0000000)==0xc0000000)
46 #define	IN_CLASSC_NET		0xffffff00
47 #define	IN_CLASSC_NSHIFT	8
48 #define	IN_CLASSC_HOST		0x000000ff
49 /*
50  * little utility routines
51  * cannot be macros because called from non-IP segments of the code.
52  */
53 
54 in_lnaof(ip_addr)
55 struct in_addr ip_addr;
56 {
57     /*
58      * 1/27/84 Berkeley interface of programs to kernel uses net ordering
59      * This subr used for SIOCSIFADDR ioctl
60      */
61     register u_long i = ntohl(ip_addr.s_addr);
62 
63     if (IN_CLASSA(i))
64 	return ((i)&IN_CLASSA_HOST);
65     else if (IN_CLASSB(i))
66 	return ((i)&IN_CLASSB_HOST);
67     else
68 	return ((i)&IN_CLASSC_HOST);
69 }
70 
71 /*
72 #ifdef unused
73 */
74 in_netof(ip_addr)
75 struct in_addr ip_addr;
76 {
77     register u_long i = ntohl(ip_addr.s_addr);
78 
79     if (IN_CLASSA(i))
80 	return (((i)&IN_CLASSA_NET) >> IN_CLASSA_NSHIFT);
81     else if (IN_CLASSB(i))
82 	return (((i)&IN_CLASSB_NET) >> IN_CLASSB_NSHIFT);
83     else
84 	return (((i)&IN_CLASSC_NET) >> IN_CLASSC_NSHIFT);
85 }
86 /*
87 #endif
88 */
89 
90 /*
91  * hash an internet address for routing lookups
92  * host part of the address is byte-swapped to put host-specific
93  * bits in the low byte (only the low LOG2(RTHASHSIZ) bits are used by rtalloc)
94  */
95 
inet_hash(sin,hp)96 inet_hash(sin, hp)
97 register struct sockaddr_in *sin;
98 struct afhash *hp;
99 {
100     hp->afh_nethash = NETHASH(sin->sin_addr);
101     hp->afh_hosthash = HOSTHASH(sin->sin_addr.s_addr);
102 }
103 
104 inet_netmatch(sin1, sin2)
105 struct sockaddr_in *sin1, *sin2;
106 {
107 
108     return (iptonet(sin1->sin_addr) == iptonet(sin2->sin_addr));
109 }
110 
111 /*
112  * Formulate an Internet address from network + host.
113  */
in_makeaddr(net,host)114 struct in_addr in_makeaddr(net, host)
115 u_long net, host;
116 {
117     register struct in_ifaddr *ia;
118     register u_long mask;
119     u_long addr;
120 
121     if (IN_CLASSA(net))
122 	mask = IN_CLASSA_HOST;
123     else if (IN_CLASSB(net))
124 	mask = IN_CLASSB_HOST;
125     else
126 	mask = IN_CLASSC_HOST;
127 
128     for (ia = in_ifaddr; ia; ia = ia->ia_next)
129 	if ((ia->ia_netmask & net) == ia->ia_net)
130 	{
131 	    mask = ~ia->ia_subnetmask;
132 	    break;
133 	}
134 
135     addr = htonl(net | (host & mask));
136     return (*(struct in_addr *)&addr);
137 }
138 
139 /*
140  * Return 1 if the address is a local broadcast address.
141  */
142 in_broadcast(in)
143 struct in_addr in;
144 {
145     register struct in_ifaddr *ia;
146 
147     /*
148      * Look through the list of addresses for a match
149      * with a broadcast address.
150      */
151     for (ia = in_ifaddr; ia; ia = ia->ia_next)
152 	if (((struct sockaddr_in *)&ia->ia_broadaddr)->sin_addr.s_addr ==
153 	in.s_addr && (ia->ia_ifp->if_flags & IFF_BROADCAST))
154 	return (TRUE);
155     return (FALSE);
156 }
157 
158 /*
159  * Return the network number from an internet address.
160  */
161 iptonet (in)
162 struct in_addr in;
163 {
164     register u_long i = ntohl(in.s_addr);
165     register u_long net;
166     register struct in_ifaddr *ia;
167 
168     if (IN_CLASSA(i))
169 	net = i & IN_CLASSA_NET;
170     else if (IN_CLASSB(i))
171 	net = i & IN_CLASSB_NET;
172     else
173 	net = i & IN_CLASSC_NET;
174 
175     /*
176      * Check whether network is a subnet;
177      * if so, return subnet number.
178      */
179     for (ia = in_ifaddr; ia; ia = ia->ia_next)
180 	if (net == ia->ia_net)
181 	    return (i & ia->ia_subnetmask);
182 
183     return (net);
184 }
185 
186 #ifdef unused
187 /*
188  * Return the host portion of an internet address.
189  */
190 iptohost (in)
191 struct in_addr in;
192 {
193     register u_long i = ntohl(in.s_addr);
194     register u_long net, host;
195     register struct in_ifaddr *ia;
196 
197     if (IN_CLASSA(i))
198     {
199 	net = i & IN_CLASSA_NET;
200 	host = i & IN_CLASSA_HOST;
201     }
202     else if (IN_CLASSB(i))
203     {
204 	net = i & IN_CLASSB_NET;
205 	host = i & IN_CLASSB_HOST;
206     }
207     else
208     {
209 	net = i & IN_CLASSC_NET;
210 	host = i & IN_CLASSC_HOST;
211     }
212 
213     /*
214      * Check whether network is a subnet;
215      * if so, use the modified interpretation of `host'.
216      */
217     for (ia = in_ifaddr; ia; ia = ia->ia_next)
218 	if (net == ia->ia_net)
219 	    return (host & ~ia->ia_subnetmask);
220 
221     return (host);
222 }
223 #endif
224 
225 #ifdef unused
226 /*
227  * Return TRUE if an internet address is for a ``local'' host
228  * (one to which we have a connection through a local logical net).
229  */
230 in_localaddr(in)
231 struct in_addr in;
232 {
233     register u_long i = ntohl(in.s_addr);
234     register u_long net;
235     register struct in_ifaddr *ia;
236 
237     if (IN_CLASSA(i))
238 	net = i & IN_CLASSA_NET;
239     else if (IN_CLASSB(i))
240 	net = i & IN_CLASSB_NET;
241     else
242 	net = i & IN_CLASSC_NET;
243 
244     for (ia = in_ifaddr; ia; ia = ia->ia_next)
245 	if (net == ia->ia_net)
246 	    return (TRUE);
247 
248     return (FALSE);
249 }
250 #endif
251 
252 /*
253  * because defaults are a bit messy here, the ARP and interface layers
254  * are both handled here....
255  */
256 
257 /* ARGSUSED */
in_ioctl(optname,optval)258 in_ioctl(optname, optval)
259 int optname;
260 struct mbuf **optval;
261 {
262     extern struct ifnet *ifunit();
263     register struct ifreq *ifr = (struct ifreq *)optval;
264     register struct ifnet *ifp = ifunit(ifr->ifr_name);
265     register struct in_ifaddr *ia = NULL;
266     struct ifaddr *ifa;
267     struct mbuf *m;
268     int error = 0;
269 
270     /*
271      *  ARP
272      */
273     switch (optname)
274     {
275       case SIOCSARP:
276       case SIOCDARP:
277 	if (!suser())
278 	    return(u.u_error);
279 
280 	/* fall thru */
281 
282       case SIOCGARP:
283 	return(arpioctl(optname,(caddr_t)optval));
284     }
285 
286     /*
287      * Find address for this interface, if it exists.
288      */
289     if (ifp)
290 	for (ia = in_ifaddr; ia; ia = ia->ia_next)
291 	    if (ia->ia_ifp == ifp)
292 		break;
293 
294     /*
295      * Interface stuff
296      */
297 
298     switch (optname)
299     {
300 
301       case SIOCGIFADDR:
302       case SIOCGIFBRDADDR:
303       case SIOCGIFDSTADDR:
304       case SIOCGIFNETMASK:
305 	if (ia == (struct in_ifaddr *) NULL)
306 	    return(EADDRNOTAVAIL);
307 	break;
308 
309       case SIOCSIFADDR:
310       case SIOCSIFDSTADDR:
311       case SIOCSIFBRDADDR:
312       case SIOCSIFNETMASK:
313 	if (!suser())
314 	    return(u.u_error);
315 
316 	if (ifp == NULL)
317 	    panic("in_control");
318 	if (ia == (struct in_ifaddr *) NULL)
319 	{
320 	    m = m_getclr(M_WAIT, MT_IFADDR);
321 	    if (m == (struct mbuf *)NULL)
322 		return(ENOBUFS);
323 	    if (ia = in_ifaddr)
324 	    {
325 		for ( ; ia->ia_next; ia = ia->ia_next)
326 		    ;
327 		ia->ia_next = mtod(m, struct in_ifaddr *);
328 	    }
329 	    else
330 	        in_ifaddr = mtod(m, struct in_ifaddr *);
331 	    ia = mtod(m, struct in_ifaddr *);
332 	    if (ifa = ifp->if_addrlist)
333 	    {
334 		for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
335 		    ;
336 		ifa->ifa_next = (struct ifaddr *) ia;
337 	    }
338 	    else
339 	        ifp->if_addrlist = (struct ifaddr *) ia;
340 	    ia->ia_ifp = ifp;
341 	    IA_SIN(ia)->sin_family = AF_INET;
342 	}
343 	break;
344     }
345 
346     switch (optname)
347     {
348 
349       case SIOCGIFADDR:
350 	ifr->ifr_addr = ia->ia_addr;
351 	break;
352 
353       case SIOCGIFBRDADDR:
354 	if ((ifp->if_flags & IFF_BROADCAST) == 0)
355 	    return(EINVAL);
356 	ifr->ifr_dstaddr = ia->ia_broadaddr;
357 	break;
358 
359       case SIOCGIFDSTADDR:
360 	if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
361 	    return(EINVAL);
362 	ifr->ifr_dstaddr = ia->ia_dstaddr;
363 	break;
364 
365       case SIOCGIFNETMASK:
366 #define	satosin(sa)	((struct sockaddr_in *)(sa))
367 	satosin(&ifr->ifr_addr)->sin_family = AF_INET;
368 	satosin(&ifr->ifr_addr)->sin_addr.s_addr = htonl(ia->ia_subnetmask);
369 	break;
370 
371       case SIOCSIFDSTADDR:
372 	if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
373 	    return(EINVAL);
374 
375 	if (ifp->if_ioctl &&
376 	    (error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia)))
377 	    return(error);
378 
379 	ia->ia_dstaddr = ifr->ifr_dstaddr;
380 	break;
381 
382       case SIOCSIFBRDADDR:
383 	if ((ifp->if_flags & IFF_BROADCAST) == 0)
384 	    return(EINVAL);
385 
386 	ia->ia_broadaddr = ifr->ifr_broadaddr;
387 	break;
388 
389       case SIOCSIFADDR:
390 	return(in_ifinit(ifp, ia, (struct sockaddr_in *)&ifr->ifr_addr));
391 
392       case SIOCSIFNETMASK:
393 	ia->ia_subnetmask =
394 	    ntohl(satosin(&ifr->ifr_addr)->sin_addr.s_addr);
395 	break;
396 
397       default:
398 	if (ifp == NULL || ifp->if_ioctl == 0)
399 	    return(EOPNOTSUPP);
400 
401 	return(((*ifp->if_ioctl)(ifp, optname, (caddr_t)optval)));
402     }
403 
404     return (0);
405 }
406 
407 /*
408  * Initialize an interface's internet address
409  * and routing table entry.
410  */
in_ifinit(ifp,ia,sin)411 in_ifinit(ifp, ia, sin)
412 register struct ifnet *ifp;
413 register struct in_ifaddr *ia;
414 struct sockaddr_in *sin;
415 {
416     register u_long i = ntohl(sin->sin_addr.s_addr);
417     struct sockaddr_in netaddr;
418     int s = splimp(), error;
419 
420     bzero((caddr_t)&netaddr, sizeof (netaddr));
421     netaddr.sin_family = AF_INET;
422     /*
423      * Delete any previous route for an old address.
424      */
425     if (ia->ia_flags & IFA_ROUTE)
426     {
427 	if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
428 	{
429 	    netaddr.sin_addr = in_makeaddr(ia->ia_subnet, INADDR_ANY);
430 	    rtinit((struct sockaddr *)&netaddr, &ia->ia_addr, -1);
431 	}
432 	else
433 	    rtinit((struct sockaddr *)&ia->ia_dstaddr, &ia->ia_addr, -1);
434 	ia->ia_flags &= ~IFA_ROUTE;
435     }
436     ia->ia_addr = *(struct sockaddr *)sin;
437     if (IN_CLASSA(i))
438 	ia->ia_netmask = IN_CLASSA_NET;
439     else if (IN_CLASSB(i))
440 	ia->ia_netmask = IN_CLASSB_NET;
441     else
442 	ia->ia_netmask = IN_CLASSC_NET;
443     ia->ia_net = i & ia->ia_netmask;
444     /*
445      * The subnet mask includes at least the standard network part,
446      * but may already have been set to a larger value.
447      */
448     ia->ia_subnetmask |= ia->ia_netmask;
449     ia->ia_subnet = i & ia->ia_subnetmask;
450     if (ifp->if_flags & IFF_BROADCAST)
451     {
452 	ia->ia_broadaddr.sa_family = AF_INET;
453 	satoipa(&ia->ia_broadaddr) = in_makeaddr(ia->ia_subnet, INADDR_BROADCAST);
454     }
455 
456     /*
457      * Give the interface a chance to initialize
458      * if this is its first address,
459      * and to validate the address if necessary.
460      */
461     if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia)))
462     {
463 	splx(s);
464 	bzero((caddr_t)&ia->ia_addr, sizeof(ia->ia_addr));
465 	return (error);
466     }
467     splx(s);
468     /*
469      * Add route for the network.
470      */
471     if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
472     {
473 	netaddr.sin_addr = in_makeaddr(ia->ia_subnet, INADDR_ANY);
474 	rtinit((struct sockaddr *)&netaddr, &ia->ia_addr, RTF_UP);
475     }
476     else
477 	rtinit((struct sockaddr *)&ia->ia_dstaddr, &ia->ia_addr, RTF_HOST|RTF_UP);
478     ia->ia_flags |= IFA_ROUTE;
479     return (0);
480 }
481 
482 /*
483  * return address info for specified address
484  */
485 
in_iawithaddr(addr,bcast)486 struct in_ifaddr *in_iawithaddr(addr,bcast)
487 struct in_addr addr;
488 int bcast;	/* look for broadcast addrs */
489 {
490     register struct in_ifaddr *ia;
491 
492     for (ia = in_ifaddr; ia; ia = ia->ia_next)
493     {
494 	if (IA_INADDR(ia).s_addr == addr.s_addr)
495 	    return(ia);
496 
497 	if (bcast)
498 	    if (IA_B_INADDR(ia).s_addr == addr.s_addr)
499 	        return(ia);
500     }
501 
502     return(ia);
503 }
504 
in_iawithnet(addr)505 struct in_ifaddr *in_iawithnet(addr)
506 struct in_addr addr;
507 {
508     register struct in_ifaddr *ia;
509     register u_long net;
510 
511     net = iptonet(addr);
512 
513     for(ia = in_ifaddr; ia; ia = ia->ia_next)
514     {
515 	if (iptonet(IA_INADDR(ia)) == net)
516 	    return(ia);
517     }
518 
519     return(ia);
520 }
521 
in_iafromif(ifp)522 struct in_ifaddr *in_iafromif(ifp)
523 struct ifnet *ifp;
524 {
525     register struct ifaddr *ifa;
526 
527     for(ifa = ifp->if_addrlist; ifa != NULL; ifa = ifa->ifa_next)
528 	if (ifa->ifa_addr.sa_family == AF_INET)
529 	    break;
530 
531     return((struct in_ifaddr *)ifa);
532 }
533 
534 /*
535 #ifdef unused
536 */
537 /*
538  * Return address info for specified internet network.
539  */
in_iaonnetof(net)540 struct in_ifaddr *in_iaonnetof(net)
541 u_long net;
542 {
543     register struct in_ifaddr *ia;
544 
545     for (ia = in_ifaddr; ia; ia = ia->ia_next)
546 	if (ia->ia_subnet == net)
547 	    return (ia);
548 
549     return ((struct in_ifaddr *) NULL);
550 }
551 /*
552 #endif
553 */
554 #endif
555