fix mbuf leak in smallest way, check in for 4.3 betas
[unix-history] / usr / src / sys / netns / ns.c
CommitLineData
8ae0e4b4
KM
1/*
2 * Copyright (c) 1982 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 *
6 * @(#)ns.c 6.2 (Berkeley) %G%
7 */
de9bc7de
KS
8
9#include "param.h"
10#include "mbuf.h"
11#include "ioctl.h"
12#include "protosw.h"
13#include "socket.h"
14#include "socketvar.h"
15#include "uio.h"
16#include "dir.h"
17#include "user.h"
18
19
20#include "../net/if.h"
21#include "../net/route.h"
22#include "../net/af.h"
23
24#include "ns.h"
25#include "ns_if.h"
26
27#ifdef NS
28
29struct ns_ifaddr *ns_ifaddr;
30
31ns_hash(sns, hp)
32 register struct sockaddr_ns *sns;
33 struct afhash *hp;
34{
35 register long hash = 0;
36 register u_short *s = sns->sns_addr.x_host.s_host;
37
38 hp->afh_nethash = ns_netof(sns->sns_addr);
39 hash = *s++; hash <<= 8; hash += *s++; hash <<= 8; hash += *s;
40 hp->afh_hosthash = hash;
41}
42
43
44ns_netmatch(sns1, sns2)
45 struct sockaddr_ns *sns1, *sns2;
46{
47
48 return (ns_netof(sns1->sns_addr) == ns_netof(sns2->sns_addr));
49}
50
51/*
52 * Generic internet control operations (ioctl's).
53 */
54ns_control(so, cmd, data, ifp)
55 struct socket *so;
56 int cmd;
57 caddr_t data;
58 register struct ifnet *ifp;
59{
60 register struct ifreq *ifr = (struct ifreq *)data;
61 register struct ns_ifaddr *ia;
62 struct ifaddr *ifa;
63 struct mbuf *m;
64 int error;
65
66 if (!suser())
67 return (u.u_error);
68
69 /*
70 * Find address for this interface, if it exists.
71 */
72 for (ia = ns_ifaddr; ia; ia = ia->ia_next)
73 if (ia->ia_ifp == ifp)
74 break;
75
76 switch (cmd) {
77
78 case SIOCGIFADDR:
79 case SIOCGIFBRDADDR:
80 case SIOCGIFDSTADDR:
81 if (ia == (struct ns_ifaddr *)0)
82 return (EADDRNOTAVAIL);
83 break;
84
85 case SIOCSIFDSTADDR:
86 return (EOPNOTSUPP);
87
88 case SIOCSIFADDR:
89 if (ia == (struct ns_ifaddr *)0) {
90 m = m_getclr(M_WAIT, MT_IFADDR);
91 if (m == (struct mbuf *)NULL)
92 return (ENOBUFS);
93 if (ia = ns_ifaddr) {
94 for ( ; ia->ia_next; ia = ia->ia_next)
95 ;
96 ia->ia_next = mtod(m, struct ns_ifaddr *);
97 } else
98 ns_ifaddr = mtod(m, struct ns_ifaddr *);
99 ia = mtod(m, struct ns_ifaddr *);
100 if (ifa = ifp->if_addrlist) {
101 for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
102 ;
103 ifa->ifa_next = (struct ifaddr *) ia;
104 } else
105 ifp->if_addrlist = (struct ifaddr *) ia;
106 ia->ia_ifp = ifp;
107 IA_SNS(ia)->sns_family = AF_NS;
108 }
109 break;
110 }
111
112 switch (cmd) {
113
114 case SIOCGIFADDR:
115 ifr->ifr_addr = ia->ia_addr;
116 break;
117
118 case SIOCGIFBRDADDR:
119 if (ia == (struct ns_ifaddr *)0)
120 return (EADDRNOTAVAIL);
121 if ((ifp->if_flags & IFF_BROADCAST) == 0)
122 return (EINVAL);
123 ifr->ifr_dstaddr = ia->ia_broadaddr;
124 break;
125
126 case SIOCGIFDSTADDR:
127 if (ia == (struct ns_ifaddr *)0)
128 return (EADDRNOTAVAIL);
129 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
130 return (EINVAL);
131 ifr->ifr_dstaddr = ia->ia_dstaddr;
132 break;
133
134 case SIOCSIFADDR:
135 return
136 (ns_ifinit(ifp, ia, (struct sockaddr_ns *)&ifr->ifr_addr));
137
138 default:
139 if (ifp->if_ioctl == 0)
140 return (EOPNOTSUPP);
141 return ((*ifp->if_ioctl)(ifp, cmd, data));
142 }
143 return (0);
144}
145
146/*
147 * Initialize an interface's internet address
148 * and routing table entry.
149 */
150ns_ifinit(ifp, ia, sns)
151 register struct ifnet *ifp;
152 register struct ns_ifaddr *ia;
153 struct sockaddr_ns *sns;
154{
155 struct sockaddr_ns netaddr;
156 register union ns_host *h = &(IA_SNS(ia)->sns_addr.x_host);
157 int s = splimp(), error;
158
159 /*
160 * The convention we shall adopt for naming is that
161 * a supplied address of zero means that "we don't care".
162 * if there is a single interface, use the address of that
163 * interface as our 6 byte host address.
164 * if there are multiple interfaces, use any address already
165 * used.
166 *
167 * If we have gotten into trouble and want to reset back to
168 * virginity, we recognize a request of the broadcast address.
169 */
170 if (ns_hosteqnh(sns->sns_addr.x_host, ns_broadhost)) {
171 ns_thishost = ns_zerohost;
172 splx(s);
173 return(EINVAL);
174 }
175
176 /*
177 * Delete any previous route for an old address.
178 */
179
180 bzero((caddr_t)&netaddr, sizeof (netaddr));
181 netaddr.sns_family = AF_NS;
182 netaddr.sns_addr.x_host = ns_broadhost;
183 netaddr.sns_addr.x_net = ia->ia_net;
184 if (ia->ia_flags & IFA_ROUTE) {
185 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
186 rtinit((struct sockaddr *)&netaddr, &ia->ia_addr, -1);
187 } else
188 rtinit((struct sockaddr *)&ia->ia_dstaddr, &ia->ia_addr, -1);
189 }
190
191 /*
192 * Set up new addresses.
193 */
194 ia->ia_addr = *(struct sockaddr *)sns;
195 ia->ia_net = sns->sns_addr.x_net;
196 netaddr.sns_addr.x_net = ia->ia_net;
197 if (ifp->if_flags & IFF_BROADCAST) {
198 ia->ia_broadaddr = * (struct sockaddr *) &netaddr;
199 }
200 /*
201 * Point to point links are a little touchier --
202 * We have to have an address of our own first,
203 * and will use the supplied address as that of the other end.
204 */
205 if (ifp->if_flags & IFF_POINTOPOINT) {
206 struct sockaddr_ns *sns2 = IA_SNS(ia);
207 if (ns_hosteqnh(ns_zerohost,ns_thishost))
208 return(EINVAL);
209 ia->ia_dstaddr = ia->ia_addr;
210 sns2->sns_addr.x_host = ns_thishost;
211 sns->sns_addr.x_host = ns_thishost;
212 }
213 /*
214 * Give the interface a chance to initialize
215 * if this is its first address,
216 * and to validate the address if necessary.
217 */
218
219 if (ns_hosteqnh(ns_thishost, ns_zerohost)) {
220 if (ifp->if_ioctl &&
221 (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) {
222 splx(s);
223 return (error);
224 }
225 ns_thishost = *h;
226 } else if (ns_hosteqnh(sns->sns_addr.x_host, ns_zerohost)
227 || ns_hosteqnh(sns->sns_addr.x_host, ns_thishost)) {
228 *h = ns_thishost;
229 if (ifp->if_ioctl &&
230 (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) {
231 splx(s);
232 return (error);
233 }
234 if(!ns_hosteqnh(ns_thishost,*h)) {
235 splx(s);
236 return (EINVAL);
237 }
238 } else {
239 splx(s);
240 return(EINVAL);
241 }
242 /*
243 * Add route for the network.
244 */
245 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
246 rtinit((struct sockaddr *)&netaddr, &ia->ia_addr, RTF_UP);
247 } else
248 rtinit((struct sockaddr *)&ia->ia_dstaddr, &ia->ia_addr,
249 RTF_HOST|RTF_UP);
250 ia->ia_flags |= IFA_ROUTE;
251 return(0);
252}
253
254/*
255 * Return address info for specified internet network.
256 */
257struct ns_ifaddr *
258ns_iaonnetof(net)
259 union ns_net net;
260{
261 register struct ns_ifaddr *ia;
262
263#define NtoL(x) (*(long *)(&(x)))
264 for (ia = ns_ifaddr; ia; ia = ia->ia_next)
265 if (NtoL(ia->ia_net) == NtoL(net))
266 return (ia);
267 return ((struct ns_ifaddr *)0);
268}
269#endif