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
00031
00032
00033
00034
00035
00036 #include "dhcpd.h"
00037 #if defined (USE_BPF_SEND) || defined (USE_BPF_RECEIVE) \
00038 || defined (USE_LPF_RECEIVE)
00039 # if defined (USE_LPF_RECEIVE)
00040 # include <asm/types.h>
00041 # include <linux/filter.h>
00042 # define bpf_insn sock_filter
00043 # else
00044 # include <sys/ioctl.h>
00045 # include <sys/uio.h>
00046 # include <net/bpf.h>
00047 # if defined (NEED_OSF_PFILT_HACKS)
00048 # include <net/pfilt.h>
00049 # endif
00050 # endif
00051
00052 #include <netinet/in_systm.h>
00053 #include "includes/netinet/ip.h"
00054 #include "includes/netinet/udp.h"
00055 #include "includes/netinet/if_ether.h"
00056 #endif
00057
00058 #if defined(USE_BPF_SEND) || defined(USE_BPF_RECEIVE) || defined(USE_BPF_HWADDR)
00059 #include <net/if_types.h>
00060 #include <ifaddrs.h>
00061 #endif
00062
00063 #include <errno.h>
00064
00065
00066
00067
00068 #ifdef USE_BPF_SEND
00069 void if_reinitialize_send (info)
00070 struct interface_info *info;
00071 {
00072 }
00073 #endif
00074
00075 #ifdef USE_BPF_RECEIVE
00076 void if_reinitialize_receive (info)
00077 struct interface_info *info;
00078 {
00079 }
00080 #endif
00081
00082
00083
00084
00085
00086 #if defined (USE_BPF_SEND) || defined (USE_BPF_RECEIVE)
00087 int if_register_bpf (info)
00088 struct interface_info *info;
00089 {
00090 int sock;
00091 char filename[50];
00092 int b;
00093
00094
00095 for (b = 0; 1; b++) {
00096
00097 sprintf(filename, BPF_FORMAT, b);
00098 sock = open (filename, O_RDWR | O_CLOEXEC, 0);
00099 if (sock < 0) {
00100 if (errno == EBUSY) {
00101 continue;
00102 } else {
00103 if (!b)
00104 log_fatal ("No bpf devices.%s%s%s",
00105 " Please read the README",
00106 " section for your operating",
00107 " system.");
00108 log_fatal ("Can't find free bpf: %m");
00109 }
00110 } else {
00111 break;
00112 }
00113 }
00114
00115
00116 if (ioctl (sock, BIOCSETIF, info -> ifp) < 0)
00117 log_fatal ("Can't attach interface %s to bpf device %s: %m",
00118 info -> name, filename);
00119
00120 get_hw_addr(info->name, &info->hw_address);
00121
00122 return sock;
00123 }
00124 #endif
00125
00126 #ifdef USE_BPF_SEND
00127 void if_register_send (info)
00128 struct interface_info *info;
00129 {
00130
00131
00132 #ifndef USE_BPF_RECEIVE
00133 info -> wfdesc = if_register_bpf (info, interface);
00134 #else
00135 info -> wfdesc = info -> rfdesc;
00136 #endif
00137 if (!quiet_interface_discovery)
00138 log_info ("Sending on BPF/%s/%s%s%s",
00139 info -> name,
00140 print_hw_addr (info -> hw_address.hbuf [0],
00141 info -> hw_address.hlen - 1,
00142 &info -> hw_address.hbuf [1]),
00143 (info -> shared_network ? "/" : ""),
00144 (info -> shared_network ?
00145 info -> shared_network -> name : ""));
00146 }
00147
00148 void if_deregister_send (info)
00149 struct interface_info *info;
00150 {
00151
00152
00153 #ifndef USE_BPF_RECEIVE
00154 close (info -> wfdesc);
00155 #endif
00156 info -> wfdesc = -1;
00157
00158 if (!quiet_interface_discovery)
00159 log_info ("Disabling output on BPF/%s/%s%s%s",
00160 info -> name,
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 #if defined (USE_BPF_RECEIVE) || defined (USE_LPF_RECEIVE)
00171
00172
00173
00174
00175 struct bpf_insn dhcp_bpf_filter [] = {
00176
00177 BPF_STMT (BPF_LD + BPF_H + BPF_ABS, 12),
00178 BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 0, 8),
00179
00180
00181 BPF_STMT (BPF_LD + BPF_B + BPF_ABS, 23),
00182 BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 6),
00183
00184
00185 BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 20),
00186 BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 4, 0),
00187
00188
00189 BPF_STMT (BPF_LDX + BPF_B + BPF_MSH, 14),
00190
00191
00192 BPF_STMT (BPF_LD + BPF_H + BPF_IND, 16),
00193 BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 67, 0, 1),
00194
00195
00196 BPF_STMT(BPF_RET+BPF_K, (u_int)-1),
00197
00198
00199 BPF_STMT(BPF_RET+BPF_K, 0),
00200 };
00201
00202
00203
00204
00205
00206
00207
00208
00209 struct bpf_insn dhcp_ib_bpf_filter [] = {
00210
00211
00212 BPF_STMT(BPF_LD + BPF_B + BPF_ABS, 9),
00213 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 6),
00214
00215
00216 BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 6),
00217 BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 4, 0),
00218
00219
00220 BPF_STMT(BPF_LDX + BPF_B + BPF_MSH, 0),
00221
00222
00223 BPF_STMT(BPF_LD + BPF_H + BPF_IND, 2),
00224 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 67, 0, 1),
00225
00226
00227 BPF_STMT(BPF_RET + BPF_K, (u_int)-1),
00228
00229
00230 BPF_STMT(BPF_RET + BPF_K, 0),
00231 };
00232
00233 #if defined (DEC_FDDI)
00234 struct bpf_insn *bpf_fddi_filter;
00235 #endif
00236
00237 int dhcp_bpf_filter_len = sizeof dhcp_bpf_filter / sizeof (struct bpf_insn);
00238 int dhcp_ib_bpf_filter_len = sizeof dhcp_ib_bpf_filter / sizeof (struct bpf_insn);
00239
00240 #if defined (HAVE_TR_SUPPORT)
00241 struct bpf_insn dhcp_bpf_tr_filter [] = {
00242
00243
00244
00245
00246 BPF_STMT(BPF_RET+BPF_K, (u_int)-1),
00247
00248
00249 BPF_STMT(BPF_RET+BPF_K, 0),
00250 };
00251
00252 int dhcp_bpf_tr_filter_len = (sizeof dhcp_bpf_tr_filter /
00253 sizeof (struct bpf_insn));
00254 #endif
00255 #endif
00256
00257 #if defined (USE_BPF_RECEIVE)
00258 void if_register_receive (info)
00259 struct interface_info *info;
00260 {
00261 int flag = 1;
00262 struct bpf_version v;
00263 struct bpf_program p;
00264 #ifdef NEED_OSF_PFILT_HACKS
00265 u_int32_t bits;
00266 #endif
00267 #ifdef DEC_FDDI
00268 int link_layer;
00269 #endif
00270
00271
00272 info -> rfdesc = if_register_bpf (info);
00273
00274
00275 if (ioctl (info -> rfdesc, BIOCVERSION, &v) < 0)
00276 log_fatal ("Can't get BPF version: %m");
00277
00278 if (v.bv_major != BPF_MAJOR_VERSION ||
00279 v.bv_minor < BPF_MINOR_VERSION)
00280 log_fatal ("BPF version mismatch - recompile DHCP!");
00281
00282
00283
00284
00285 if (ioctl (info -> rfdesc, BIOCIMMEDIATE, &flag) < 0)
00286 log_fatal ("Can't set immediate mode on bpf device: %m");
00287
00288 #ifdef NEED_OSF_PFILT_HACKS
00289
00290 if (ioctl(info -> rfdesc, EIOCALLOWCOPYALL, &flag) < 0)
00291 log_fatal ("Can't set ALLOWCOPYALL: %m");
00292
00293
00294 bits = 0;
00295 if (ioctl (info -> rfdesc, EIOCMBIS, &bits) < 0)
00296 log_fatal ("Can't clear pfilt bits: %m");
00297
00298
00299 bits = ENBATCH | ENCOPYALL | ENBPFHDR;
00300 if (ioctl (info -> rfdesc, EIOCMBIS, &bits) < 0)
00301 log_fatal ("Can't set ENBATCH|ENCOPYALL|ENBPFHDR: %m");
00302 #endif
00303
00304 if (ioctl (info -> rfdesc, BIOCGBLEN, &info -> rbuf_max) < 0)
00305 log_fatal ("Can't get bpf buffer length: %m");
00306 info -> rbuf = dmalloc (info -> rbuf_max, MDL);
00307 if (!info -> rbuf)
00308 log_fatal ("Can't allocate %ld bytes for bpf input buffer.",
00309 (long)(info -> rbuf_max));
00310 info -> rbuf_offset = 0;
00311 info -> rbuf_len = 0;
00312
00313
00314 p.bf_len = dhcp_bpf_filter_len;
00315
00316 #ifdef DEC_FDDI
00317
00318 if (ioctl(info -> rfdesc, BIOCGDLT, &link_layer) >= 0 &&
00319 link_layer == DLT_FDDI) {
00320 if (!bpf_fddi_filter) {
00321 bpf_fddi_filter = dmalloc (sizeof bpf_fddi_filter,
00322 MDL);
00323 if (!bpf_fddi_filter)
00324 log_fatal ("No memory for FDDI filter.");
00325 memcpy (bpf_fddi_filter,
00326 dhcp_bpf_filter, sizeof dhcp_bpf_filter);
00327
00328
00329
00330
00331
00332 bpf_fddi_filter[0].k += 10;
00333 bpf_fddi_filter[2].k += 10;
00334 bpf_fddi_filter[4].k += 10;
00335 bpf_fddi_filter[6].k += 10;
00336 bpf_fddi_filter[7].k += 10;
00337 }
00338 p.bf_insns = bpf_fddi_filter;
00339 } else
00340 #endif
00341 p.bf_insns = dhcp_bpf_filter;
00342
00343
00344
00345
00346 dhcp_bpf_filter [8].k = ntohs (local_port);
00347
00348 if (ioctl (info -> rfdesc, BIOCSETF, &p) < 0)
00349 log_fatal ("Can't install packet filter program: %m");
00350 if (!quiet_interface_discovery)
00351 log_info ("Listening on BPF/%s/%s%s%s",
00352 info -> name,
00353 print_hw_addr (info -> hw_address.hbuf [0],
00354 info -> hw_address.hlen - 1,
00355 &info -> hw_address.hbuf [1]),
00356 (info -> shared_network ? "/" : ""),
00357 (info -> shared_network ?
00358 info -> shared_network -> name : ""));
00359 }
00360
00361 void if_deregister_receive (info)
00362 struct interface_info *info;
00363 {
00364 close (info -> rfdesc);
00365 info -> rfdesc = -1;
00366
00367 if (!quiet_interface_discovery)
00368 log_info ("Disabling input on BPF/%s/%s%s%s",
00369 info -> name,
00370 print_hw_addr (info -> hw_address.hbuf [0],
00371 info -> hw_address.hlen - 1,
00372 &info -> hw_address.hbuf [1]),
00373 (info -> shared_network ? "/" : ""),
00374 (info -> shared_network ?
00375 info -> shared_network -> name : ""));
00376 }
00377 #endif
00378
00379 #ifdef USE_BPF_SEND
00380 ssize_t send_packet (interface, packet, raw, len, from, to, hto)
00381 struct interface_info *interface;
00382 struct packet *packet;
00383 struct dhcp_packet *raw;
00384 size_t len;
00385 struct in_addr from;
00386 struct sockaddr_in *to;
00387 struct hardware *hto;
00388 {
00389 unsigned hbufp = 0, ibufp = 0;
00390 double hw [4];
00391 double ip [32];
00392 struct iovec iov [3];
00393 int result;
00394
00395 if (!strcmp (interface -> name, "fallback"))
00396 return send_fallback (interface, packet, raw,
00397 len, from, to, hto);
00398
00399 if (hto == NULL && interface->anycast_mac_addr.hlen)
00400 hto = &interface->anycast_mac_addr;
00401
00402
00403 assemble_hw_header (interface, (unsigned char *)hw, &hbufp, hto);
00404 assemble_udp_ip_header (interface,
00405 (unsigned char *)ip, &ibufp, from.s_addr,
00406 to -> sin_addr.s_addr, to -> sin_port,
00407 (unsigned char *)raw, len);
00408
00409
00410 iov [0].iov_base = ((char *)hw);
00411 iov [0].iov_len = hbufp;
00412 iov [1].iov_base = ((char *)ip);
00413 iov [1].iov_len = ibufp;
00414 iov [2].iov_base = (char *)raw;
00415 iov [2].iov_len = len;
00416
00417 result = writev(interface -> wfdesc, iov, 3);
00418 if (result < 0)
00419 log_error ("send_packet: %m");
00420 return result;
00421 }
00422 #endif
00423
00424 #ifdef USE_BPF_RECEIVE
00425 ssize_t receive_packet (interface, buf, len, from, hfrom)
00426 struct interface_info *interface;
00427 unsigned char *buf;
00428 size_t len;
00429 struct sockaddr_in *from;
00430 struct hardware *hfrom;
00431 {
00432 int length = 0;
00433 int offset = 0;
00434 struct bpf_hdr hdr;
00435 unsigned paylen;
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446 if (interface->rbuf_offset >= interface->rbuf_len) {
00447 length = read(interface->rfdesc, interface->rbuf,
00448 (size_t)interface->rbuf_max);
00449 if (length <= 0) {
00450 #ifdef __FreeBSD__
00451 if (errno == ENXIO) {
00452 #else
00453 if (errno == EIO) {
00454 #endif
00455 dhcp_interface_remove
00456 ((omapi_object_t *)interface, NULL);
00457 }
00458 return (length);
00459 }
00460 interface->rbuf_offset = 0;
00461 interface->rbuf_len = BPF_WORDALIGN(length);
00462 }
00463
00464 do {
00465
00466
00467 if (interface->rbuf_len -
00468 interface->rbuf_offset < sizeof hdr) {
00469 interface->rbuf_offset = interface->rbuf_len;
00470 continue;
00471 }
00472
00473
00474 memcpy(&hdr, &interface->rbuf[interface->rbuf_offset],
00475 sizeof hdr);
00476
00477
00478
00479 if (interface->rbuf_offset +
00480 hdr.bh_hdrlen + hdr.bh_caplen > interface->rbuf_len) {
00481 interface->rbuf_offset = interface->rbuf_len;
00482 continue;
00483 }
00484
00485
00486
00487
00488 if (hdr.bh_caplen != hdr.bh_datalen) {
00489 interface->rbuf_offset =
00490 BPF_WORDALIGN(interface->rbuf_offset +
00491 hdr.bh_hdrlen + hdr.bh_caplen);
00492 continue;
00493 }
00494
00495
00496 interface->rbuf_offset += hdr.bh_hdrlen;
00497
00498
00499 offset = decode_hw_header(interface, interface->rbuf,
00500 interface->rbuf_offset, hfrom);
00501
00502
00503
00504
00505 if (offset < 0) {
00506 interface->rbuf_offset =
00507 BPF_WORDALIGN(interface->rbuf_offset +
00508 hdr.bh_caplen);
00509 continue;
00510 }
00511 interface->rbuf_offset += offset;
00512 hdr.bh_caplen -= offset;
00513
00514
00515 offset = decode_udp_ip_header(interface, interface->rbuf,
00516 interface->rbuf_offset,
00517 from, hdr.bh_caplen, &paylen, 0);
00518
00519
00520 if (offset < 0) {
00521 interface->rbuf_offset =
00522 BPF_WORDALIGN(interface->rbuf_offset +
00523 hdr.bh_caplen);
00524 continue;
00525 }
00526 interface->rbuf_offset = interface->rbuf_offset + offset;
00527 hdr.bh_caplen -= offset;
00528
00529
00530
00531
00532 if (hdr.bh_caplen > len) {
00533 interface->rbuf_offset =
00534 BPF_WORDALIGN(interface->rbuf_offset +
00535 hdr.bh_caplen);
00536 continue;
00537 }
00538
00539
00540 memcpy(buf, interface->rbuf + interface->rbuf_offset, paylen);
00541 interface->rbuf_offset =
00542 BPF_WORDALIGN(interface->rbuf_offset + hdr.bh_caplen);
00543 return paylen;
00544 } while (interface->rbuf_offset < interface->rbuf_len);
00545
00546 return (0);
00547 }
00548
00549 int can_unicast_without_arp (ip)
00550 struct interface_info *ip;
00551 {
00552 return 1;
00553 }
00554
00555 int can_receive_unicast_unconfigured (ip)
00556 struct interface_info *ip;
00557 {
00558 return 1;
00559 }
00560
00561 int supports_multiple_interfaces (ip)
00562 struct interface_info *ip;
00563 {
00564 return 1;
00565 }
00566
00567 void maybe_setup_fallback ()
00568 {
00569 isc_result_t status;
00570 struct interface_info *fbi = (struct interface_info *)0;
00571 if (setup_fallback (&fbi, MDL)) {
00572 if_register_fallback (fbi);
00573 status = omapi_register_io_object ((omapi_object_t *)fbi,
00574 if_readsocket, 0,
00575 fallback_discard, 0, 0);
00576 if (status != ISC_R_SUCCESS)
00577 log_fatal ("Can't register I/O handle for %s: %s",
00578 fbi -> name, isc_result_totext (status));
00579 interface_dereference (&fbi, MDL);
00580 }
00581 }
00582 #endif
00583
00584 #if defined(USE_BPF_RECEIVE) || defined(USE_BPF_HWADDR)
00585 void
00586 get_hw_addr(const char *name, struct hardware *hw) {
00587 struct ifaddrs *ifa;
00588 struct ifaddrs *p;
00589 struct sockaddr_dl *sa;
00590
00591 if (getifaddrs(&ifa) != 0) {
00592 log_fatal("Error getting interface information; %m");
00593 }
00594
00595
00596
00597
00598 sa = NULL;
00599 for (p=ifa; (p != NULL) && (sa == NULL); p = p->ifa_next) {
00600 if ((p->ifa_addr->sa_family == AF_LINK) &&
00601 !strcmp(p->ifa_name, name)) {
00602 sa = (struct sockaddr_dl *)p->ifa_addr;
00603 }
00604 }
00605 if (sa == NULL) {
00606 log_fatal("No interface called '%s'", name);
00607 }
00608
00609
00610
00611
00612 switch (sa->sdl_type) {
00613 case IFT_ETHER:
00614 hw->hlen = sa->sdl_alen + 1;
00615 hw->hbuf[0] = HTYPE_ETHER;
00616 memcpy(&hw->hbuf[1], LLADDR(sa), sa->sdl_alen);
00617 break;
00618 case IFT_ISO88023:
00619 case IFT_ISO88024:
00620 case IFT_ISO88025:
00621 case IFT_ISO88026:
00622 hw->hlen = sa->sdl_alen + 1;
00623 hw->hbuf[0] = HTYPE_IEEE802;
00624 memcpy(&hw->hbuf[1], LLADDR(sa), sa->sdl_alen);
00625 break;
00626 #ifdef IFT_FDDI
00627 case IFT_FDDI:
00628 hw->hlen = sa->sdl_alen + 1;
00629 hw->hbuf[0] = HTYPE_FDDI;
00630 memcpy(&hw->hbuf[1], LLADDR(sa), sa->sdl_alen);
00631 break;
00632 #endif
00633 #if defined(IFT_PPP)
00634 case IFT_PPP:
00635 if (local_family != AF_INET6)
00636 log_fatal("Unsupported device type %d for \"%s\"",
00637 sa->sdl_type, name);
00638 hw->hlen = 0;
00639 hw->hbuf[0] = HTYPE_RESERVED;
00640
00641
00642
00643 hw->hbuf[1] = 0xde;
00644 hw->hbuf[2] = 0xad;
00645 hw->hbuf[3] = 0xbe;
00646 hw->hbuf[4] = 0xef;
00647 break;
00648 #endif
00649 default:
00650 log_fatal("Unsupported device type %d for \"%s\"",
00651 sa->sdl_type, name);
00652 }
00653
00654 freeifaddrs(ifa);
00655 }
00656 #endif