/* handle fd events on a smb_krb5_socket */ static void smb_krb5_socket_handler(struct tevent_context *ev, struct tevent_fd *fde, uint16_t flags, void *private_data) { struct smb_krb5_socket *smb_krb5 = talloc_get_type(private_data, struct smb_krb5_socket); switch (smb_krb5->hi->proto) { case KRB5_KRBHST_UDP: if (flags & TEVENT_FD_READ) { smb_krb5_socket_recv(smb_krb5); return; } if (flags & TEVENT_FD_WRITE) { smb_krb5_socket_send(smb_krb5); return; } /* not reached */ return; case KRB5_KRBHST_TCP: if (flags & TEVENT_FD_READ) { packet_recv(smb_krb5->packet); return; } if (flags & TEVENT_FD_WRITE) { packet_queue_run(smb_krb5->packet); return; } /* not reached */ return; case KRB5_KRBHST_HTTP: /* can't happen */ break; } }
/* receive some data on a winbind connection */ static void wbsrv_recv(struct stream_connection *conn, uint16_t flags) { struct wbsrv_connection *wbconn = talloc_get_type(conn->private_data, struct wbsrv_connection); packet_recv(wbconn->packet); }
/* used to put packets on event boundaries */ static void packet_next_event(struct tevent_context *ev, struct tevent_timer *te, struct timeval t, void *private_data) { struct packet_context *pc = talloc_get_type(private_data, struct packet_context); if (pc->num_read != 0 && pc->packet_size != 0 && pc->packet_size <= pc->num_read) { packet_recv(pc); } }
/* handler for winrepl events */ static void wrepl_handler(struct tevent_context *ev, struct tevent_fd *fde, uint16_t flags, void *private_data) { struct wrepl_socket *wrepl_socket = talloc_get_type(private_data, struct wrepl_socket); if (flags & EVENT_FD_READ) { packet_recv(wrepl_socket->packet); return; } if (flags & EVENT_FD_WRITE) { packet_queue_run(wrepl_socket->packet); } }
/* an event has happened on the socket */ static void smbcli_transport_event_handler(struct tevent_context *ev, struct tevent_fd *fde, uint16_t flags, void *private_data) { struct smbcli_transport *transport = talloc_get_type(private_data, struct smbcli_transport); if (flags & EVENT_FD_READ) { packet_recv(transport->packet); return; } if (flags & EVENT_FD_WRITE) { packet_queue_run(transport->packet); } }
void MainWindow::on_tvChDown_clicked() { //tv ch down packet_set(&user_packet,0,number,2,2,2,0); ret=packet_send(devfd,user_packet); printf("send ret=%d\n",ret); ret=packet_recv(devfd,&recv_packet); printf("recv ret=%d\n"); printf("recv_packet.src=%d\n",recv_packet.src); printf("recv_packet.dst=%d\n",recv_packet.dst); printf("recv_packet.optype=%d\n",recv_packet.optype); printf("recv_packet.operation=%d\n",recv_packet.operation); printf("recv_packet.operand[0]=%d\n",recv_packet.operand[0]); printf("recv_packet.operand[1]=%d\n",recv_packet.operand[1]); recv_packet.operand[1]= recv_packet.operand[1]-1; packet_set(&recv_packet,0,number,1,2,1,1); ret=packet_send(devfd,recv_packet); printf("send ret=%d\n",ret); packet_set(&user_packet,0,number,2,1,1,0); ret=packet_send(devfd,user_packet); printf("send ret=%d\n",ret); ret=packet_recv(devfd,&recv_packet); printf("recv ret=%d\n"); printf("recv_packet.src=%d\n",recv_packet.src); printf("recv_packet.dst=%d\n",recv_packet.dst); printf("recv_packet.optype=%d\n",recv_packet.optype); printf("recv_packet.operation=%d\n",recv_packet.operation); printf("recv_packet.operand[0]=%d\n",recv_packet.operand[0]); printf("recv_packet.operand[1]=%d\n",recv_packet.operand[1]); }
void MainWindow::on_Power_4_clicked() { //ait con power on/off packet_set(&user_packet,0,number,4,1,1,0); ret=packet_send(devfd,user_packet); printf("send ret=%d\n",ret); ret=packet_recv(devfd,&recv_packet); printf("recv ret=%d\n"); printf("recv_packet.src=%d\n",recv_packet.src); printf("recv_packet.dst=%d\n",recv_packet.dst); printf("recv_packet.optype=%d\n",recv_packet.optype); printf("recv_packet.operation=%d\n",recv_packet.operation); printf("recv_packet.operand[0]=%d\n",recv_packet.operand[0]); printf("recv_packet.operand[1]=%d\n",recv_packet.operand[1]); }
static struct packet *handler_recv(int fd) { struct packet *pkt = NULL; #ifdef HADM_COMPRESS { struct z_packet *z_pkt; z_pkt = z_packet_recv(fd); if (!z_pkt) goto out; pkt = unpack_z_packet(z_pkt); free_z_packet(z_pkt); } #else pkt = packet_recv(fd); #endif return pkt; }
/* process some read/write requests that are pending return false if the socket is dead */ _PUBLIC_ bool smbcli_transport_process(struct smbcli_transport *transport) { NTSTATUS status; size_t npending; packet_queue_run(transport->packet); if (transport->socket->sock == NULL) { return false; } status = socket_pending(transport->socket->sock, &npending); if (NT_STATUS_IS_OK(status) && npending > 0) { packet_recv(transport->packet); } if (transport->socket->sock == NULL) { return false; } return true; }
/* called when a IO is triggered by the events system */ static void sock_io_handler(struct tevent_context *ev, struct tevent_fd *fde, uint16_t flags, void *private_data) { struct dcecli_connection *p = talloc_get_type(private_data, struct dcecli_connection); struct sock_private *sock = (struct sock_private *)p->transport.private_data; if (flags & EVENT_FD_WRITE) { packet_queue_run(sock->packet); return; } if (sock->sock == NULL) { return; } if (flags & EVENT_FD_READ) { packet_recv(sock->packet); } }
/* called when a LDAP socket becomes readable */ void ldapsrv_recv(struct stream_connection *c, uint16_t flags) { struct ldapsrv_connection *conn = talloc_get_type(c->private_data, struct ldapsrv_connection); if (conn->limits.ite) { /* clean initial timeout if any */ talloc_free(conn->limits.ite); conn->limits.ite = NULL; } if (conn->limits.te) { /* clean idle timeout if any */ talloc_free(conn->limits.te); conn->limits.te = NULL; } packet_recv(conn->packet); /* set idle timeout */ conn->limits.te = event_add_timed(c->event.ctx, conn, timeval_current_ofs(conn->limits.conn_idle_time, 0), ldapsrv_conn_idle_timeout, conn); }
int process_client(CLIENT *client) { int readcount; PACKET packet; packet.recv_fd = client->sockfd; packet.recv = socket_recv; readcount = packet_recv(&packet); if (readcount <= 0) { //client close this connection printf("%s connection close\n", client->ip); close(client->sockfd); client->sockfd = -1; kill_sniffer(); return -1; } else { printf("packet type is %d\n", packet.type); switch (packet.type) { case CMD_OPEN_SNIFFER: { //open sniffer int pid; signal(SIGCHLD, SIG_IGN); pid = fork(); if (pid < 0) { perror("Create thread:"); exit(1); } else if (pid == 0) { execlp("/opt/sniffer/bin/sniffer", "/opt/sniffer/bin/sniffer", client->ip, (char *) 0); _exit(1); } } default: break; } //switch (packet.type) } return 0; }
int main() { SOCKET sniffer; struct in_addr addr; int in; char hostname[100]; struct hostent *local; WSADATA wsa; // Init Winsock printf("\nInitialising Winsock... "); if (WSAStartup(MAKEWORD(2,2), &wsa) != 0) { printf("WSAStartup() failed.\n"); return 1; } printf("done\n"); // Create a RAW Socket printf("Creating RAW Socket... "); //sniffer = socket(AF_INET, SOCK_RAW, IPPROTO_IP); sniffer = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); if (sniffer == INVALID_SOCKET) { printf("Failed to create raw socket.\n"); return 1; } printf("Created.\n"); // Retrive the local hostname if (gethostname(hostname, sizeof(hostname)) == SOCKET_ERROR) { printf("Error : %d\n", WSAGetLastError()); return 1; } printf("\nHost name : %s\n",hostname); // Retrive the available IPs of the local host local = gethostbyname(hostname); printf("\nAvailable Network Interfaces : \n"); if (local == NULL) { printf("Error : %d\n", WSAGetLastError()); return 1; } for (i = 0; local->h_addr_list[i] != 0; ++i) { memcpy(&addr, local->h_addr_list[i], sizeof(struct in_addr)); printf("Interface Number : %d Address : %s\n", i, inet_ntoa(addr)); } printf("Enter the interface number you would like to sniff : "); scanf("%d",&in); memset(&dest, 0, sizeof(dest)); memcpy(&dest.sin_addr.s_addr, local->h_addr_list[in], sizeof(dest.sin_addr.s_addr)); dest.sin_family = AF_INET; dest.sin_port = 0; printf("\nBinding socket to local system and port 0... "); if (bind(sniffer,(struct sockaddr *)&dest,sizeof(dest)) == SOCKET_ERROR) { printf("bind(%s) failed.\n", inet_ntoa(addr)); return 1; } printf("Binding successful\n"); // Enable this socket with the power to sniff : SIO_RCVALL is the key Receive ALL ;) j=1; printf("Setting socket to sniff..."); if (WSAIoctl(sniffer, SIO_RCVALL, &j, sizeof(j), 0, 0, (LPDWORD) &in , 0 , 0) == SOCKET_ERROR) { printf("WSAIoctl() failed.\n"); return 1; } printf("Socket set.\n"); // Begin printf("Started Sniffing\n"); printf("Packet Capture Statistics...\n"); packet_recv(sniffer); //Happy Sniffing // End closesocket(sniffer); WSACleanup(); return 0; }
/* These two routines could be changed to use a circular buffer of * some kind, or linked lists, or ... */ static NTSTATUS gensec_socket_recv(struct socket_context *sock, void *buf, size_t wantlen, size_t *nread) { struct gensec_socket *gensec_socket = talloc_get_type(sock->private_data, struct gensec_socket); if (!gensec_socket->wrap) { return socket_recv(gensec_socket->socket, buf, wantlen, nread); } gensec_socket->error = NT_STATUS_OK; if (gensec_socket->read_buffer.length == 0) { /* Process any data on the socket, into the read buffer. At * this point, the socket is not available for read any * longer */ packet_recv(gensec_socket->packet); if (gensec_socket->eof) { *nread = 0; return NT_STATUS_OK; } if (!NT_STATUS_IS_OK(gensec_socket->error)) { return gensec_socket->error; } if (gensec_socket->read_buffer.length == 0) { /* Clearly we don't have the entire SASL packet yet, * so it has not been written into the buffer */ *nread = 0; return STATUS_MORE_ENTRIES; } } *nread = MIN(wantlen, gensec_socket->read_buffer.length); memcpy(buf, gensec_socket->read_buffer.data, *nread); if (gensec_socket->read_buffer.length > *nread) { memmove(gensec_socket->read_buffer.data, gensec_socket->read_buffer.data + *nread, gensec_socket->read_buffer.length - *nread); } gensec_socket->read_buffer.length -= *nread; gensec_socket->read_buffer.data = talloc_realloc(gensec_socket, gensec_socket->read_buffer.data, uint8_t, gensec_socket->read_buffer.length); if (gensec_socket->read_buffer.length && gensec_socket->in_extra_read == 0 && gensec_socket->recv_handler) { /* Manually call a read event, to get this moving * again (as the socket should be dry, so the normal * event handler won't trigger) */ tevent_add_timer(gensec_socket->ev, gensec_socket, timeval_zero(), gensec_socket_trigger_read, gensec_socket); } return NT_STATUS_OK; }
int main(int argc, char **argv) { char *x; const char *keydir = 0; long long i; struct pollfd p[6]; struct pollfd *q; struct pollfd *watch0; struct pollfd *watch1; struct pollfd *watchtochild; struct pollfd *watchfromchild1; struct pollfd *watchfromchild2; struct pollfd *watchselfpipe; int exitsignal, exitcode; signal(SIGPIPE, SIG_IGN); signal(SIGALRM, timeout); log_init(0, "tinysshd", 0, 0); if (argc < 2) die_usage(USAGE); if (!argv[0]) die_usage(USAGE); for (;;) { if (!argv[1]) break; if (argv[1][0] != '-') break; x = *++argv; if (x[0] == '-' && x[1] == 0) break; if (x[0] == '-' && x[1] == '-' && x[2] == 0) break; while (*++x) { if (*x == 'q') { flagverbose = 0; continue; } if (*x == 'Q') { flagverbose = 1; continue; } if (*x == 'v') { if (flagverbose >= 2) flagverbose = 3; else flagverbose = 2; continue; } if (*x == 'o') { cryptotypeselected |= sshcrypto_TYPEOLDCRYPTO; continue; } if (*x == 'O') { cryptotypeselected &= ~sshcrypto_TYPEOLDCRYPTO; continue; } if (*x == 's') { cryptotypeselected |= sshcrypto_TYPENEWCRYPTO; continue; } if (*x == 'S') { cryptotypeselected &= ~sshcrypto_TYPENEWCRYPTO; continue; } if (*x == 'p') { cryptotypeselected |= sshcrypto_TYPEPQCRYPTO; continue; } if (*x == 'P') { cryptotypeselected &= ~sshcrypto_TYPEPQCRYPTO; continue; } if (*x == 'l') { flaglogger = 1; continue; } if (*x == 'L') { flaglogger = 0; continue; } if (*x == 'x') { if (x[1]) { channel_subsystem_add(x + 1); break; } if (argv[1]) { channel_subsystem_add(*++argv); break; } } die_usage(USAGE); } } keydir = *++argv; if (!keydir) die_usage(USAGE); log_init(flagverbose, "tinysshd", 1, flaglogger); connectioninfo(channel.localip, channel.localport, channel.remoteip, channel.remoteport); log_i4("connection from ", channel.remoteip, ":", channel.remoteport); channel_subsystem_log(); global_init(); blocking_disable(0); blocking_disable(1); blocking_disable(2); /* get server longterm keys */ fdwd = open_cwd(); if (fdwd == -1) die_fatal("unable to open current directory", 0, 0); if (chdir(keydir) == -1) die_fatal("unable to chdir to", keydir, 0); for (i = 0; sshcrypto_keys[i].name; ++i) sshcrypto_keys[i].sign_flagserver |= sshcrypto_kexs[i].cryptotype & cryptotypeselected; for (i = 0; sshcrypto_keys[i].name; ++i) sshcrypto_keys[i].sign_flagclient |= sshcrypto_kexs[i].cryptotype & cryptotypeselected; for (i = 0; sshcrypto_kexs[i].name; ++i) sshcrypto_kexs[i].flagenabled |= sshcrypto_kexs[i].cryptotype & cryptotypeselected; for (i = 0; sshcrypto_ciphers[i].name; ++i) sshcrypto_ciphers[i].flagenabled |= sshcrypto_ciphers[i].cryptotype & cryptotypeselected; /* read public keys */ for (i = 0; sshcrypto_keys[i].name; ++i) { if (!sshcrypto_keys[i].sign_flagserver) continue; if (load(sshcrypto_keys[i].sign_publickeyfilename, sshcrypto_keys[i].sign_publickey, sshcrypto_keys[i].sign_publickeybytes) == -1) { sshcrypto_keys[i].sign_flagserver = 0; if (errno == ENOENT) continue; die_fatal("unable to read public key from file", keydir, sshcrypto_keys[i].sign_publickeyfilename); } } if (fchdir(fdwd) == -1) die_fatal("unable to change directory to working directory", 0, 0); close(fdwd); /* set timeout */ alarm(60); /* send and receive hello */ if (!packet_hello_send()) die_fatal("unable to send hello-string", 0, 0); if (!packet_hello_receive()) die_fatal("unable to receive hello-string", 0, 0); /* send and receive kex */ if (!packet_kex_send()) die_fatal("unable to send kex-message", 0, 0); if (!packet_kex_receive()) die_fatal("unable to receive kex-message", 0, 0); rekeying: /* rekeying */ alarm(60); if (packet.flagrekeying == 1) { buf_purge(&packet.kexrecv); buf_put(&packet.kexrecv, b1.buf, b1.len); if (!packet_kex_send()) die_fatal("unable to send kex-message", 0, 0); } /* send and receive kexdh */ if (!packet_kexdh(keydir, &b1, &b2)) die_fatal("unable to subprocess kexdh", 0, 0); if (packet.flagkeys) log_d1("rekeying: done"); packet.flagkeys = 1; /* note: comunication is encrypted */ /* authentication + authorization */ if (packet.flagauthorized == 0) { if (!packet_auth(&b1, &b2)) die_fatal("authentication failed", 0, 0); packet.flagauthorized = 1; } /* note: user is authenticated and authorized */ alarm(3600); /* main loop */ for (;;) { if (channel_iseof()) if (!packet.sendbuf.len) if (packet.flagchanneleofreceived) break; watch0 = watch1 = 0; watchtochild = watchfromchild1 = watchfromchild2 = 0; watchselfpipe = 0; q = p; if (packet_sendisready()) { watch1 = q; q->fd = 1; q->events = POLLOUT; ++q; } if (packet_recvisready()) { watch0 = q; q->fd = 0; q->events = POLLIN; ++q; } if (channel_writeisready()) { watchtochild = q; q->fd = channel_getfd0(); q->events = POLLOUT; ++q; } if (channel_readisready() && packet_putisready()) { watchfromchild1 = q; q->fd = channel_getfd1(); q->events = POLLIN; ++q; } if (channel_extendedreadisready() && packet_putisready()) { watchfromchild2 = q; q->fd = channel_getfd2(); q->events = POLLIN; ++q; } if (selfpipe[0] != -1) { watchselfpipe = q; q->fd = selfpipe[0]; q->events = POLLIN; ++q; } if (poll(p, q - p, 60000) < 0) { watch0 = watch1 = 0; watchtochild = watchfromchild1 = watchfromchild2 = 0; watchselfpipe = 0; } else { if (watch0) if (!watch0->revents) watch0 = 0; if (watch1) if (!watch1->revents) watch1 = 0; if (watchfromchild1) if (!watchfromchild1->revents) watchfromchild1 = 0; if (watchfromchild2) if (!watchfromchild2->revents) watchfromchild2 = 0; if (watchtochild) if (!watchtochild->revents) watchtochild = 0; if (watchselfpipe) if (!watchselfpipe->revents) watchselfpipe = 0; } if (watchtochild) { /* write data to child */ if (!channel_write()) die_fatal("unable to write data to child", 0, 0); /* try to adjust window */ if (!packet_channel_send_windowadjust(&b1)) die_fatal("unable to send data to network", 0, 0); } /* read data from child */ if (watchfromchild1) packet_channel_send_data(&b2); if (watchfromchild2) packet_channel_send_extendeddata(&b2); /* check child */ if (channel_iseof()) { if (selfpipe[0] == -1) if (open_pipe(selfpipe) == -1) die_fatal("unable to open pipe", 0, 0); signal(SIGCHLD, trigger); if (channel_waitnohang(&exitsignal, &exitcode)) { packet_channel_send_eof(&b2); if (!packet_channel_send_close(&b2, exitsignal, exitcode)) die_fatal("unable to close channel", 0, 0); } } /* send data to network */ if (watch1) if (!packet_send()) die_fatal("unable to send data to network", 0, 0); /* receive data from network */ if (watch0) { alarm(3600); /* refresh timeout */ if (!packet_recv()) { if (channel_iseof()) break; /* XXX */ die_fatal("unable to receive data from network", 0, 0); } } /* process packets */ for (;;) { if (!packet_get(&b1, 0)) { if (!errno) break; die_fatal("unable to get packets from network", 0, 0); } if (b1.len < 1) break; /* XXX */ switch (b1.buf[0]) { case SSH_MSG_CHANNEL_OPEN: if (!packet_channel_open(&b1, &b2)) die_fatal("unable to open channel", 0, 0); break; case SSH_MSG_CHANNEL_REQUEST: if (!packet_channel_request(&b1, &b2)) die_fatal("unable to handle channel-request", 0, 0); break; case SSH_MSG_CHANNEL_DATA: if (!packet_channel_recv_data(&b1)) die_fatal("unable to handle channel-data", 0, 0); break; case SSH_MSG_CHANNEL_EXTENDED_DATA: if (!packet_channel_recv_extendeddata(&b1)) die_fatal("unable to handle channel-extended-data", 0, 0); break; case SSH_MSG_CHANNEL_WINDOW_ADJUST: if (!packet_channel_recv_windowadjust(&b1)) die_fatal("unable to handle channel-window-adjust", 0, 0); break; case SSH_MSG_CHANNEL_EOF: if (!packet_channel_recv_eof(&b1)) die_fatal("unable to handle channel-eof", 0, 0); break; case SSH_MSG_CHANNEL_CLOSE: if (!packet_channel_recv_close(&b1)) die_fatal("unable to handle channel-close", 0, 0); break; case SSH_MSG_KEXINIT: goto rekeying; default: if (!packet_unimplemented(&b1)) die_fatal("unable to send SSH_MSG_UNIMPLEMENTED message", 0, 0); } } } log_i1("finished"); global_die(0); return 111; }
/* receive some data on a KDC connection */ static void kdc_tcp_recv_handler(struct stream_connection *conn, uint16_t flags) { struct kdc_tcp_connection *kdcconn = talloc_get_type(conn->private_data, struct kdc_tcp_connection); packet_recv(kdcconn->packet); }
int main(void) { int devfd; int cmd; int ret; struct packet user_packet; struct packet recv_packet; int i=0; int dst; int type; int operation; int operand1,operand2; devfd=device_open(); if(devfd==0) { printf("open error\n"); return 0; } printf("devfd=%d\n",devfd); while(1) { printf("0. broadcast 1. send 2. recv 3. listget 4. exit: "); scanf("%d",&cmd); if(cmd==0) { packet_set(&user_packet,0,255,2,0,0,0); ret=packet_send(devfd,user_packet); printf("send ret=%d\n",ret); /* ret=packet_recv(devfd,&recv_packet); printf("recv ret=%d\n"); printf("recv_packet.src=%d\n",recv_packet.src); printf("recv_packet.dst=%d\n",recv_packet.dst); printf("recv_packet.optype=%d\n",recv_packet.optype); printf("recv_packet.operation=%d\n",recv_packet.operation); printf("recv_packet.operand[0]=%d\n",recv_packet.operand[0]); printf("recv_packet.operand[1]=%d\n",recv_packet.operand[1]);*/ } else if(cmd==1) { printf("input dev number: "); scanf("%d",&dst); printf("input type: "); scanf("%d",&type); printf("input dev operation: "); scanf("%d",&operation); printf("input operand[0]: "); scanf("%d",&operand1); printf("input operand[1]: "); scanf("%d",&operand2); packet_set(&user_packet,0,dst,type,operation,operand1,operand2); ret=packet_send(devfd,user_packet); printf("send ret=%d\n",ret); } else if(cmd==2) { ret=packet_recv(devfd,&recv_packet); printf("recv ret=%d\n"); printf("recv_packet.src=%d\n",recv_packet.src); printf("recv_packet.dst=%d\n",recv_packet.dst); printf("recv_packet.optype=%d\n",recv_packet.optype); printf("recv_packet.operation=%d\n",recv_packet.operation); printf("recv_packet.operand[0]=%d\n",recv_packet.operand[0]); printf("recv_packet.operand[1]=%d\n",recv_packet.operand[1]); } else if(cmd==3) { get_devlist(devfd,dev_list); for(i=0; i<254; i++) { if(dev_list[i].addr==255) break; printf("dev_list[%d].addr=%d\n",i,dev_list[i].addr); printf("dev_list[%d].devicetype=%d\n",i,dev_list[i].devicetype); } } else if(cmd==4) break; } return 0; }
* 2 = DHCPOFFER (from dhcp_proto.h) * 5 = DHCPACK * 6 = DHCPNACK */ static int dhcp_recv(struct netdev *dev) { struct bootp_hdr bootp; uint8_t dhcp_options[1500]; struct iovec iov[] = { /* [0] = ip + udp header */ [1] = {&bootp, sizeof(struct bootp_hdr)}, [2] = {dhcp_options, sizeof(dhcp_options)} }; int ret; ret = packet_recv(dev, iov, 3); if (ret <= 0) return ret; dprintf("\n dhcp xid %08x ", dev->bootp.xid); if (ret < sizeof(struct bootp_hdr) || bootp.op != BOOTP_REPLY || /* RFC951 7.5 */ bootp.xid != dev->bootp.xid || memcmp(bootp.chaddr, dev->hwaddr, 16)) return 0; ret -= sizeof(struct bootp_hdr); return dhcp_parse(dev, &bootp, dhcp_options, ret); }