00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "dhcpd.h"
00031 #if defined (USE_NIT_SEND) || defined (USE_NIT_RECEIVE)
00032 #include <sys/ioctl.h>
00033 #include <sys/uio.h>
00034
00035 #include <sys/time.h>
00036 #include <net/nit.h>
00037 #include <net/nit_if.h>
00038 #include <net/nit_pf.h>
00039 #include <net/nit_buf.h>
00040 #include <sys/stropts.h>
00041 #include <net/packetfilt.h>
00042
00043 #include <netinet/in_systm.h>
00044 #include "includes/netinet/ip.h"
00045 #include "includes/netinet/udp.h"
00046 #include "includes/netinet/if_ether.h"
00047
00048
00049
00050
00051 #ifdef USE_NIT_SEND
00052 void if_reinitialize_send (info)
00053 struct interface_info *info;
00054 {
00055 }
00056 #endif
00057
00058 #ifdef USE_NIT_RECEIVE
00059 void if_reinitialize_receive (info)
00060 struct interface_info *info;
00061 {
00062 }
00063 #endif
00064
00065
00066
00067
00068
00069 int if_register_nit (info)
00070 struct interface_info *info;
00071 {
00072 int sock;
00073 char filename[50];
00074 struct ifreq ifr;
00075 struct strioctl sio;
00076
00077
00078 sock = open ("/dev/nit", O_RDWR | O_CLOEXEC);
00079 if (sock < 0)
00080 log_fatal ("Can't open NIT device for %s: %m", info -> name);
00081
00082
00083 sio.ic_cmd = NIOCBIND;
00084 sio.ic_len = sizeof *(info -> ifp);
00085 sio.ic_dp = (char *)(info -> ifp);
00086 sio.ic_timout = INFTIM;
00087 if (ioctl (sock, I_STR, &sio) < 0)
00088 log_fatal ("Can't attach interface %s to nit device: %m",
00089 info -> name);
00090
00091
00092 sio.ic_cmd = SIOCGIFADDR;
00093 sio.ic_len = sizeof ifr;
00094 sio.ic_dp = (char *)𝔦
00095 sio.ic_timout = INFTIM;
00096 if (ioctl (sock, I_STR, &sio) < 0)
00097 log_fatal ("Can't get physical layer address for %s: %m",
00098 info -> name);
00099
00100
00101 info -> hw_address.hlen = 7;
00102 info -> hw_address.hbuf [0] = ARPHRD_ETHER;
00103 memcpy (&info -> hw_address.hbuf [1],
00104 ifr.ifr_ifru.ifru_addr.sa_data, 6);
00105
00106 if (ioctl (sock, I_PUSH, "pf") < 0)
00107 log_fatal ("Can't push packet filter onto NIT for %s: %m",
00108 info -> name);
00109
00110 return sock;
00111 }
00112 #endif
00113
00114 #ifdef USE_NIT_SEND
00115 void if_register_send (info)
00116 struct interface_info *info;
00117 {
00118
00119
00120 #ifndef USE_NIT_RECEIVE
00121 struct packetfilt pf;
00122 struct strioctl sio;
00123
00124 info -> wfdesc = if_register_nit (info);
00125
00126 pf.Pf_Priority = 0;
00127 pf.Pf_FilterLen = 1;
00128 pf.Pf_Filter [0] = ENF_PUSHZERO;
00129
00130
00131 sio.ic_cmd = NIOCSETF;
00132 sio.ic_len = sizeof pf;
00133 sio.ic_dp = (char *)&pf;
00134 sio.ic_timout = INFTIM;
00135 if (ioctl (info -> wfdesc, I_STR, &sio) < 0)
00136 log_fatal ("Can't set NIT filter: %m");
00137 #else
00138 info -> wfdesc = info -> rfdesc;
00139 #endif
00140 if (!quiet_interface_discovery)
00141 log_info ("Sending on NIT/%s%s%s",
00142 print_hw_addr (info -> hw_address.hbuf [0],
00143 info -> hw_address.hlen - 1,
00144 &info -> hw_address.hbuf [1]),
00145 (info -> shared_network ? "/" : ""),
00146 (info -> shared_network ?
00147 info -> shared_network -> name : ""));
00148 }
00149
00150 void if_deregister_send (info)
00151 struct interface_info *info;
00152 {
00153
00154
00155 #ifndef USE_NIT_RECEIVE
00156 close (info -> wfdesc);
00157 #endif
00158 info -> wfdesc = -1;
00159 if (!quiet_interface_discovery)
00160 log_info ("Disabling output on NIT/%s%s%s",
00161 print_hw_addr (info -> hw_address.hbuf [0],
00162 info -> hw_address.hlen - 1,
00163 &info -> hw_address.hbuf [1]),
00164 (info -> shared_network ? "/" : ""),
00165 (info -> shared_network ?
00166 info -> shared_network -> name : ""));
00167 }
00168 #endif
00169
00170 #ifdef USE_NIT_RECEIVE
00171
00172
00173
00174
00175 void if_register_receive (info)
00176 struct interface_info *info;
00177 {
00178 int flag = 1;
00179 u_int32_t x;
00180 struct packetfilt pf;
00181 struct strioctl sio;
00182 u_int16_t addr [2];
00183 struct timeval t;
00184
00185
00186 info -> rfdesc = if_register_nit (info);
00187
00188
00189
00190 x = 0;
00191 if (ioctl (info -> rfdesc, NIOCSSNAP, &x) < 0)
00192 log_fatal ("Can't set NIT snap length on %s: %m", info -> name);
00193
00194
00195 if (ioctl (info -> rfdesc, I_SRDOPT, RMSGN) != 0)
00196 log_info ("I_SRDOPT failed on %s: %m", info -> name);
00197
00198 #if 0
00199
00200 if (ioctl (info -> rfdesc, I_PUSH, "nbuf") < 0)
00201 log_fatal ("Can't push chunker onto NIT STREAM: %m");
00202
00203
00204 t.tv_sec = 0;
00205 t.tv_usec = 0;
00206 if (ioctl (info -> rfdesc, NIOCSTIME, &t) < 0)
00207 log_fatal ("Can't set chunk timeout: %m");
00208 #endif
00209
00210
00211 x = 0;
00212 if (ioctl (info -> rfdesc, NIOCSFLAGS, &x) < 0)
00213 log_fatal ("Can't set NIT flags on %s: %m", info -> name);
00214
00215
00216
00217
00218
00219 pf.Pf_Priority = 0;
00220 pf.Pf_FilterLen = 0;
00221
00222 pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHWORD + 6;
00223 pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT + ENF_CAND;
00224 pf.Pf_Filter [pf.Pf_FilterLen++] = htons (ETHERTYPE_IP);
00225 pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT;
00226 pf.Pf_Filter [pf.Pf_FilterLen++] = htons (IPPROTO_UDP);
00227 pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHWORD + 11;
00228 pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT + ENF_AND;
00229 pf.Pf_Filter [pf.Pf_FilterLen++] = htons (0xFF);
00230 pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_CAND;
00231 pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHWORD + 18;
00232 pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT + ENF_CAND;
00233 pf.Pf_Filter [pf.Pf_FilterLen++] = local_port;
00234
00235
00236 sio.ic_cmd = NIOCSETF;
00237 sio.ic_len = sizeof pf;
00238 sio.ic_dp = (char *)&pf;
00239 sio.ic_timout = INFTIM;
00240 if (ioctl (info -> rfdesc, I_STR, &sio) < 0)
00241 log_fatal ("Can't set NIT filter on %s: %m", info -> name);
00242
00243 if (!quiet_interface_discovery)
00244 log_info ("Listening on NIT/%s%s%s",
00245 print_hw_addr (info -> hw_address.hbuf [0],
00246 info -> hw_address.hlen - 1,
00247 &info -> hw_address.hbuf [1]),
00248 (info -> shared_network ? "/" : ""),
00249 (info -> shared_network ?
00250 info -> shared_network -> name : ""));
00251 }
00252
00253 void if_deregister_receive (info)
00254 struct interface_info *info;
00255 {
00256
00257
00258 close (info -> rfdesc);
00259 info -> rfdesc = -1;
00260
00261 if (!quiet_interface_discovery)
00262 log_info ("Disabling input on NIT/%s%s%s",
00263 print_hw_addr (info -> hw_address.hbuf [0],
00264 info -> hw_address.hlen - 1,
00265 &info -> hw_address.hbuf [1]),
00266 (info -> shared_network ? "/" : ""),
00267 (info -> shared_network ?
00268 info -> shared_network -> name : ""));
00269 }
00270 #endif
00271
00272 #ifdef USE_NIT_SEND
00273 ssize_t send_packet (interface, packet, raw, len, from, to, hto)
00274 struct interface_info *interface;
00275 struct packet *packet;
00276 struct dhcp_packet *raw;
00277 size_t len;
00278 struct in_addr from;
00279 struct sockaddr_in *to;
00280 struct hardware *hto;
00281 {
00282 unsigned hbufp, ibufp;
00283 double hh [16];
00284 double ih [1536 / sizeof (double)];
00285 unsigned char *buf = (unsigned char *)ih;
00286 struct sockaddr *junk;
00287 struct strbuf ctl, data;
00288 struct sockaddr_in foo;
00289 int result;
00290
00291 if (!strcmp (interface -> name, "fallback"))
00292 return send_fallback (interface, packet, raw,
00293 len, from, to, hto);
00294
00295 if (hto == NULL && interface->anycast_mac_addr.hlen)
00296 hto = &interface->anycast_mac_addr;
00297
00298
00299 junk = (struct sockaddr *)&hh [0];
00300 hbufp = (((unsigned char *)&junk -> sa_data [0]) -
00301 (unsigned char *)&hh[0]);
00302 ibufp = 0;
00303
00304
00305 assemble_hw_header (interface, (unsigned char *)junk, &hbufp, hto);
00306 assemble_udp_ip_header (interface, buf, &ibufp,
00307 from.s_addr, to -> sin_addr.s_addr,
00308 to -> sin_port, (unsigned char *)raw, len);
00309
00310
00311 memcpy (buf + ibufp, raw, len);
00312
00313
00314 #if USE_SIN_LEN
00315 junk -> sa_len = hbufp - 2;
00316 #endif
00317 junk -> sa_family = AF_UNSPEC;
00318
00319
00320 ctl.buf = (char *)&hh [0];
00321 ctl.maxlen = ctl.len = hbufp;
00322 data.buf = (char *)&ih [0];
00323 data.maxlen = data.len = ibufp + len;
00324
00325 result = putmsg (interface -> wfdesc, &ctl, &data, 0);
00326 if (result < 0)
00327 log_error ("send_packet: %m");
00328 return result;
00329 }
00330 #endif
00331
00332 #ifdef USE_NIT_RECEIVE
00333 ssize_t receive_packet (interface, buf, len, from, hfrom)
00334 struct interface_info *interface;
00335 unsigned char *buf;
00336 size_t len;
00337 struct sockaddr_in *from;
00338 struct hardware *hfrom;
00339 {
00340 int nread;
00341 int length = 0;
00342 int offset = 0;
00343 unsigned char ibuf [1536];
00344 int bufix = 0;
00345 unsigned paylen;
00346
00347 length = read (interface -> rfdesc, ibuf, sizeof ibuf);
00348 if (length <= 0)
00349 return length;
00350
00351
00352 offset = decode_hw_header (interface, ibuf, bufix, hfrom);
00353
00354
00355
00356
00357 if (offset < 0) {
00358 return 0;
00359 }
00360
00361 bufix += offset;
00362 length -= offset;
00363
00364
00365 offset = decode_udp_ip_header (interface, ibuf, bufix,
00366 from, length, &paylen, 0);
00367
00368
00369 if (offset < 0)
00370 return 0;
00371
00372 bufix += offset;
00373 length -= offset;
00374
00375 if (length < paylen)
00376 log_fatal("Internal inconsistency at %s:%d.", MDL);
00377
00378
00379 memcpy(buf, &ibuf[bufix], paylen);
00380 return paylen;
00381 }
00382
00383 int can_unicast_without_arp (ip)
00384 struct interface_info *ip;
00385 {
00386 return 1;
00387 }
00388
00389 int can_receive_unicast_unconfigured (ip)
00390 struct interface_info *ip;
00391 {
00392 return 1;
00393 }
00394
00395 int supports_multiple_interfaces (ip)
00396 struct interface_info *ip;
00397 {
00398 return 1;
00399 }
00400
00401 void maybe_setup_fallback ()
00402 {
00403 isc_result_t status;
00404 struct interface_info *fbi = (struct interface_info *)0;
00405 if (setup_fallback (&fbi, MDL)) {
00406 if_register_fallback (fbi);
00407 status = omapi_register_io_object ((omapi_object_t *)fbi,
00408 if_readsocket, 0,
00409 fallback_discard, 0, 0);
00410 if (status != ISC_R_SUCCESS)
00411 log_fatal ("Can't register I/O handle for %s: %s",
00412 fbi -> name, isc_result_totext (status));
00413 interface_dereference (&fbi, MDL);
00414 }
00415 }
00416 #endif