int tftp_upcall(PACKET pkt, void * data) { struct tfconn * cn; struct udp * pup; /* get pointer to UDP header */ pup = (struct udp *)pkt->nb_prot; pup -= 1; /* Find tftp session this packet is for. */ if (data == TFTPSERVER) /* tftp server connection */ { #ifdef TFTP_SERVER int err; /* call server for new session here */ err = tfshnd(pkt->fhost, pup->ud_srcp, pkt->nb_prot); #endif /* TFTP_SERVER */ udp_free(pkt); /* do not return an error to the udp layer */ } else /* TFTP server child connection */ { cn = (struct tfconn *)data; if (cn->tf_fhost != pkt->fhost) /* sanity check */ { dtrap(); return ENP_NOT_MINE; } if (cn->tf_inbuf.udp_use) { dtrap(); /* ever happen? */ } cn->tf_inbuf.data = pkt->nb_prot; cn->tf_inbuf.dlen = pkt->nb_plen; cn->tf_inbuf.udp_use = (void*)pkt; tftprcv(cn, pup->ud_srcp); /* process the packet */ if (cn->tf_inbuf.udp_use) /* pkt may be freed in upcall */ { udp_free(pkt); cn->tf_inbuf.udp_use = (PACKET)NULL; } } return 0; }
extern int send_rescueack(unsigned short no, unsigned short lo) { ebuf_t *buf = NULL; int acksocket; char tftpnull; int res, i; /* * Open a UDP socket to the TFTP server */ acksocket = udp_socket(UDP_PROTO_TFTP); res = udp_bind(acksocket, 69); if (res < 0) { return res; } udp_connect(acksocket, ackport); for (i = 0; i < 1; i++) { buf = udp_alloc(); if (!buf) return -1; /* * Send the data */ ebuf_append_u16_be(buf, no); ebuf_append_u16_be(buf, lo); ebuf_append_bytes(buf,&tftpnull, 0); udp_send(acksocket ,buf, tftpipto); } if (buf) udp_free(buf); udp_close(acksocket); return 0; }
void tftp_udpbuffer(struct tfconn *cn, int size) { PACKET pkt; if (cn->tf_outbuf.udp_use) { pkt = (PACKET)cn->tf_outbuf.udp_use; if (pkt->nb_plen >= (unsigned)size) { /* recycle existing buffer */ pkt->nb_prot = (char *)cn->tf_outbuf.data; return; } else { udp_free(pkt); /* old packet was too small */ } } pkt = udp_alloc(size, 0); if (!pkt) /* alloc failed, clear outbuf pointers */ { cn->tf_outbuf.data = NULL; cn->tf_outbuf.dlen = 0; cn->tf_outbuf.udp_use = NULL; } else /* return buffer pointer */ { cn->tf_outbuf.data = pkt->nb_prot; cn->tf_outbuf.dlen = size; cn->tf_outbuf.udp_use = (void *)pkt; /* so we can find struct later */ } }
void udp_free_client(struct udp_client *cl) { udp_free(cl); free(cl); return; }
void tftp_udpfree(struct tfconn *cn) { PACKET pkt; pkt = (PACKET)cn->tf_outbuf.udp_use; #ifdef ZEROCOPY_API pkt->inuse = 1; /* free this copy - "unclone" it */ #endif udp_free(pkt); cn->tf_outbuf.udp_use = NULL; cn->tf_outbuf.data = NULL; }
void cmd_udp_read(int fd, short which, void *arg) { struct udp_con *con = arg; u_char buf[2048]; ssize_t len; TRACE(fd, len = read(fd, buf, sizeof(buf))); if (len == -1) { if (errno == EINTR || errno == EAGAIN) goto again; } if (len <= 0) { udp_free(con); return; } udp_send(con, buf, len); again: cmd_trigger_read(&con->cmd, 1); }
struct udp_client * udp_register_client(void) { struct udp_client *cl; cl = calloc(sizeof(*cl), 1); if (!cl) return cl; cl->cl_buf = calloc(UDP_MSG_DEFAULT_SIZE, 1); if (!cl->cl_buf) goto exit_register; cl->cl_buf_len = UDP_MSG_DEFAULT_SIZE; cl->cl_sock = -1; return cl; exit_register: if (cl) udp_free(cl); return NULL; }
void cmd_udp_eread(int fd, short which, void *arg) { extern FILE *honeyd_servicefp; struct udp_con *con = arg; char line[1024]; int nread; struct command *cmd = &con->cmd; TRACE(fd, nread = read(fd, line, sizeof(line))); if (nread <= 0) { udp_free(con); return; } if (nread == sizeof(line)) nread--; line[nread] = '\0'; honeyd_log_service(honeyd_servicefp, IP_PROTO_UDP, &con->conhdr, line); event_add(&cmd->peread, NULL); }
static int _tftpd_open(tftp_info_t *info,char *hostname,char *filename,int mode) { ebuf_t *buf = NULL; uint16_t type; int res; int retries; char ch = 0; /* * Open a UDP socket */ info->tftp_socket = udp_socket(UDP_PROTO_TFTP); info->tftp_lastblock = 0; info->tftp_error = 0; info->tftp_filemode = mode; /* * Listen for requests */ res = udp_bind(info->tftp_socket,UDP_PROTO_TFTP); if (res < 0) return res; res = CFE_ERR_TIMEOUT; for (retries = 0; retries < tftp_max_retries; retries++) { while (console_status()) { console_read(&ch,1); if (ch == 3) break; } if (ch == 3) { res = CFE_ERR_INTR; break; } buf = udp_recv_with_timeout(info->tftp_socket,tftp_recv_timeout); if (buf == NULL) continue; /* * Process the request */ ebuf_get_u16_be(buf,type); switch (type) { case TFTP_OP_RRQ: udp_connect(info->tftp_socket,(uint16_t) buf->eb_usrdata); memcpy(info->tftp_ipaddr,buf->eb_usrptr,IP_ADDR_LEN); info->tftp_blknum = 1; info->tftp_blklen = 0; res = 0; break; case TFTP_OP_WRQ: udp_connect(info->tftp_socket,(uint16_t) buf->eb_usrdata); memcpy(info->tftp_ipaddr,buf->eb_usrptr,IP_ADDR_LEN); info->tftp_blknum = 0; res = _tftp_readmore(info); break; default: /* * we aren't expecting any of these messages */ res = CFE_ERR_PROTOCOLERR; break; } udp_free(buf); break; } if (res) { udp_close(info->tftp_socket); info->tftp_socket = -1; } return res; }
static int _tftp_writemore(tftp_info_t *info) { ebuf_t *buf; uint16_t cmd,block,error; int retries; /* * If we've already written the last block, there is no more */ if (info->tftp_lastblock) return 1; if (info->tftp_error) return CFE_ERR_TIMEOUT; /* * Otherwise, send a block */ for (retries = 0; retries < tftp_max_retries; retries++) { buf = udp_alloc(); if (!buf) return -1; /* * Send the data */ ebuf_append_u16_be(buf,TFTP_OP_DATA); ebuf_append_u16_be(buf,info->tftp_blknum); ebuf_append_bytes(buf,info->tftp_data,info->tftp_blklen); udp_send(info->tftp_socket,buf,info->tftp_ipaddr); /* * Wait for some response, retransmitting as necessary */ buf = udp_recv_with_timeout(info->tftp_socket,tftp_recv_timeout); if (buf == NULL) continue; /* * Got a response, make sure it's right */ ebuf_get_u16_be(buf,cmd); if (cmd == TFTP_OP_ERROR) { ebuf_get_u16_be(buf,error); xprintf("TFTP write error %d: %s\n",error,ebuf_ptr(buf)); info->tftp_error = 1; info->tftp_lastblock = 1; udp_free(buf); return CFE_ERR_IOERR; } if (cmd != TFTP_OP_ACK) { udp_free(buf); continue; } ebuf_get_u16_be(buf,block); if (block != (info->tftp_blknum)) { udp_free(buf); continue; } /* * It's the correct response. Update the block # */ info->tftp_blknum++; if (info->tftp_blklen != TFTP_BLOCKSIZE) info->tftp_lastblock = 1; udp_free(buf); break; } /* * If we had some failure, mark the stream with an error */ if (retries == tftp_max_retries) { info->tftp_error = 1; return CFE_ERR_TIMEOUT; } return 0; }
static int _tftp_readmore(tftp_info_t *info) { ebuf_t *buf; uint16_t cmd,block; int retries; /* * If we've already read the last block, there is no more */ if (info->tftp_lastblock) return 1; if (info->tftp_error) return CFE_ERR_TIMEOUT; /* * Otherwise, ack the current block so another one will come */ for (retries = 0; retries < tftp_max_retries; retries++) { buf = udp_alloc(); if (!buf) return -1; /* * Send the ack */ ebuf_append_u16_be(buf,TFTP_OP_ACK); ebuf_append_u16_be(buf,info->tftp_blknum); udp_send(info->tftp_socket,buf,info->tftp_ipaddr); /* * Wait for some response, retransmitting as necessary */ buf = udp_recv_with_timeout(info->tftp_socket,tftp_recv_timeout); if (buf == NULL) continue; /* * Got a response, make sure it's right */ ebuf_get_u16_be(buf,cmd); if (cmd != TFTP_OP_DATA) { udp_free(buf); continue; } ebuf_get_u16_be(buf,block); if (block != (info->tftp_blknum+1)) { udp_free(buf); continue; } /* * It's the correct response. Copy the user data */ info->tftp_blknum = block; info->tftp_blklen = ebuf_length(buf); ebuf_get_bytes(buf,info->tftp_data,ebuf_length(buf)); udp_free(buf); break; } /* * If the block is less than 512 bytes long, it's the EOF block. */ if (retries == tftp_max_retries) { info->tftp_error = 1; return CFE_ERR_TIMEOUT; } if (info->tftp_blklen < TFTP_BLOCKSIZE) { info->tftp_lastblock = 1; /* EOF */ } return 0; }
static int _tftp_open(tftp_info_t *info,char *hostname,char *filename,int mode) { ebuf_t *buf = NULL; const char *datamode = "octet"; uint16_t type,error,block; int res; int retries; /* * Look up the remote host's IP address */ res = dns_lookup(hostname,info->tftp_ipaddr); if (res < 0) return res; /* * Open a UDP socket to the TFTP server */ info->tftp_socket = udp_socket(UDP_PROTO_TFTP); info->tftp_lastblock = 0; info->tftp_error = 0; info->tftp_filemode = mode; /* * Try to send the RRQ packet to open the file */ for (retries = 0; retries < tftp_max_retries; retries++) { buf = udp_alloc(); if (!buf) break; if (info->tftp_filemode == FILE_MODE_READ) { ebuf_append_u16_be(buf,TFTP_OP_RRQ); /* read file */ } else { ebuf_append_u16_be(buf,TFTP_OP_WRQ); /* write file */ } ebuf_append_bytes(buf,filename,strlen(filename)+1); ebuf_append_bytes(buf,datamode,strlen(datamode)+1); udp_send(info->tftp_socket,buf,info->tftp_ipaddr); buf = udp_recv_with_timeout(info->tftp_socket,tftp_rrq_timeout); if (buf) break; } /* * If we got no response, bail now. */ if (!buf) { udp_close(info->tftp_socket); info->tftp_socket = -1; return CFE_ERR_TIMEOUT; } /* * Otherwise, process the response. */ ebuf_get_u16_be(buf,type); switch (type) { case TFTP_OP_ACK: /* * Acks are what we get back on a WRQ command, * but are otherwise unexpected. */ if (info->tftp_filemode == FILE_MODE_WRITE) { udp_connect(info->tftp_socket,(uint16_t) buf->eb_usrdata); info->tftp_blknum = 1; info->tftp_blklen = 0; udp_free(buf); return 0; break; } /* fall through */ case TFTP_OP_RRQ: case TFTP_OP_WRQ: default: /* * we aren't expecting any of these messages */ udp_free(buf); udp_close(info->tftp_socket); info->tftp_socket = -1; return CFE_ERR_PROTOCOLERR; case TFTP_OP_ERROR: ebuf_get_u16_be(buf,error); xprintf("TFTP error %d: %s\n",error,ebuf_ptr(buf)); udp_free(buf); udp_close(info->tftp_socket); info->tftp_socket = -1; return CFE_ERR_PROTOCOLERR; case TFTP_OP_DATA: /* * Yay, we've got data! Store the first block. */ ebuf_get_u16_be(buf,block); udp_connect(info->tftp_socket,(uint16_t) buf->eb_usrdata); info->tftp_blknum = block; info->tftp_blklen = ebuf_length(buf); ebuf_get_bytes(buf,info->tftp_data,ebuf_length(buf)); udp_free(buf); if (info->tftp_blklen < TFTP_BLOCKSIZE) { info->tftp_lastblock = 1; /* EOF */ } return 0; break; } }
int psock_close(FAR struct socket *psock) { int err; /* Verify that the sockfd corresponds to valid, allocated socket */ if (!psock || psock->s_crefs <= 0) { err = EBADF; goto errout; } /* We perform the uIP close operation only if this is the last count on the socket. * (actually, I think the socket crefs only takes the values 0 and 1 right now). */ if (psock->s_crefs <= 1) { /* Perform uIP side of the close depending on the protocol type */ switch (psock->s_type) { #ifdef CONFIG_NET_PKT case SOCK_RAW: { FAR struct pkt_conn_s *conn = psock->s_conn; /* Is this the last reference to the connection structure (there * could be more if the socket was dup'ed). */ if (conn->crefs <= 1) { /* Yes... free the connection structure */ conn->crefs = 0; /* No more references on the connection */ pkt_free(psock->s_conn); /* Free uIP resources */ } else { /* No.. Just decrement the reference count */ conn->crefs--; } } break; #endif #ifdef CONFIG_NET_TCP case SOCK_STREAM: { FAR struct tcp_conn_s *conn = psock->s_conn; /* Is this the last reference to the connection structure (there * could be more if the socket was dup'ed). */ if (conn->crefs <= 1) { /* Yes... then perform the disconnection now */ tcp_unlisten(conn); /* No longer accepting connections */ conn->crefs = 0; /* Discard our reference to the connection */ err = netclose_disconnect(psock); /* Break any current connections */ if (err < 0) { /* This would normally occur only if there is a timeout * from a lingering close. */ goto errout_with_psock; } } else { /* No.. Just decrement the reference count */ conn->crefs--; } } break; #endif #ifdef CONFIG_NET_UDP case SOCK_DGRAM: { FAR struct udp_conn_s *conn = psock->s_conn; /* Is this the last reference to the connection structure (there * could be more if the socket was dup'ed). */ if (conn->crefs <= 1) { /* Yes... free the connection structure */ conn->crefs = 0; /* No more references on the connection */ udp_free(psock->s_conn); /* Free uIP resources */ } else { /* No.. Just decrement the reference count */ conn->crefs--; } } break; #endif default: err = EBADF; goto errout; } } /* Then release our reference on the socket structure containing the connection */ sock_release(psock); return OK; #ifdef CONFIG_NET_TCP errout_with_psock: sock_release(psock); #endif errout: set_errno(err); return ERROR; }
int psock_close(FAR struct socket *psock) { int err; /* Verify that the sockfd corresponds to valid, allocated socket */ if (!psock || psock->s_crefs <= 0) { err = EBADF; goto errout; } /* We perform the uIP close operation only if this is the last count on * the socket. (actually, I think the socket crefs only takes the values * 0 and 1 right now). * * It is possible for a psock to have no connection, e.g. a TCP socket * waiting in accept. */ if (psock->s_crefs <= 1 && psock->s_conn != NULL) { /* Perform uIP side of the close depending on the protocol type */ switch (psock->s_type) { #if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_LOCAL_STREAM) case SOCK_STREAM: { #ifdef CONFIG_NET_LOCAL_STREAM #ifdef CONFIG_NET_TCP if (psock->s_domain == PF_LOCAL) #endif { /* Release our reference to the local connection structure */ local_close(psock); } #endif /* CONFIG_NET_LOCAL_STREAM */ #ifdef CONFIG_NET_TCP #ifdef CONFIG_NET_LOCAL_STREAM else #endif { FAR struct tcp_conn_s *conn = psock->s_conn; /* Is this the last reference to the connection structure * (there could be more if the socket was dup'ed). */ if (conn->crefs <= 1) { /* Yes... then perform the disconnection now */ tcp_unlisten(conn); /* No longer accepting connections */ conn->crefs = 0; /* Discard our reference to the connection */ /* Break any current connections */ err = netclose_disconnect(psock); if (err < 0) { /* This would normally occur only if there is a * timeout from a lingering close. */ goto errout_with_psock; } /* Stop the network monitor */ net_stopmonitor(conn); } else { /* No.. Just decrement the reference count */ conn->crefs--; } } #endif /* CONFIG_NET_TCP || CONFIG_NET_LOCAL_STREAM */ } break; #endif #if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_LOCAL_DGRAM) case SOCK_DGRAM: { #ifdef CONFIG_NET_LOCAL_DGRAM #ifdef CONFIG_NET_UDP if (psock->s_domain == PF_LOCAL) #endif { /* Release our reference to the local connection structure */ local_close(psock); } #endif /* CONFIG_NET_LOCAL_DGRAM */ #ifdef CONFIG_NET_UDP #ifdef CONFIG_NET_LOCAL_DGRAM else #endif { FAR struct udp_conn_s *conn = psock->s_conn; /* Is this the last reference to the connection structure * (there could be more if the socket was dup'ed). */ if (conn->crefs <= 1) { /* Yes... free the connection structure */ conn->crefs = 0; udp_free(psock->s_conn); } else { /* No.. Just decrement the reference count */ conn->crefs--; } } #endif /* CONFIG_NET_UDP || CONFIG_NET_LOCAL_DGRAM */ } break; #endif #ifdef CONFIG_NET_PKT case SOCK_RAW: { FAR struct pkt_conn_s *conn = psock->s_conn; /* Is this the last reference to the connection structure (there * could be more if the socket was dup'ed). */ if (conn->crefs <= 1) { /* Yes... free the connection structure */ conn->crefs = 0; /* No more references on the connection */ pkt_free(psock->s_conn); /* Free uIP resources */ } else { /* No.. Just decrement the reference count */ conn->crefs--; } } break; #endif default: err = EBADF; goto errout; } } /* Then release our reference on the socket structure containing the connection */ sock_release(psock); return OK; #ifdef CONFIG_NET_TCP errout_with_psock: sock_release(psock); #endif errout: set_errno(err); return ERROR; }
static int _tftpd_open(tftp_info_t *info,char *hostname,char *filename,int mode) { ebuf_t *buf = NULL; uint16_t type; int res; int retries; char ch = 0; #ifdef RESCUE_MODE uint8_t asuslink[13] = "ASUSSPACELINK"; uint8_t maclink[13]="snxxxxxxxxxxx"; unsigned char tftpmask[4] = { 0xff, 0xff, 0xff, 0x00 }; int i; char tftpnull; uint8_t ipaddr[4] = { 0xc0, 0xa8, 0x01, 0x0c }; uint8_t hwaddr[6] = { 0x00, 0xe0, 0x18, 0x00, 0x3e, 0xc4 }; #endif /* * Open a UDP socket */ info->tftp_socket = udp_socket(UDP_PROTO_TFTP); info->tftp_lastblock = 0; info->tftp_error = 0; info->tftp_filemode = mode; /* * Listen for requests */ res = udp_bind(info->tftp_socket,UDP_PROTO_TFTP); if (res < 0) return res; res = CFE_ERR_TIMEOUT; for (retries = 0; retries < tftp_max_retries; retries++) { while (console_status()) { console_read(&ch,1); if (ch == 3) break; } if (ch == 3) { res = CFE_ERR_INTR; break; } buf = udp_recv_with_timeout(info->tftp_socket,tftp_recv_timeout); if (buf == NULL) continue; /* * Process the request */ ebuf_get_u16_be(buf,type); switch (type) { case TFTP_OP_RRQ: #ifdef RESCUE_MODE udp_connect(info->tftp_socket,(uint16_t) buf->eb_usrdata); ackport = buf->eb_usrdata; memcpy(info->tftp_ipaddr,buf->eb_usrptr,IP_ADDR_LEN); info->tftp_blknum = 1; info->tftp_blklen = 0; for (i=0; i<13; i++) { if (buf->eb_ptr[i] != asuslink[i]) break; } if (i==13) { tftpipfrom[0]=buf->eb_ptr[16]; tftpipfrom[1]=buf->eb_ptr[15]; tftpipfrom[2]=buf->eb_ptr[14]; tftpipfrom[3]=buf->eb_ptr[13]; tftpipto[0]=buf->eb_usrptr[0]; tftpipto[1]=buf->eb_usrptr[1]; tftpipto[2]=buf->eb_usrptr[2]; tftpipto[3]=buf->eb_usrptr[3]; net_setparam(NET_IPADDR,tftpipfrom); net_setparam(NET_NETMASK,tftpmask); net_setparam(NET_GATEWAY,tftpipfrom); ui_myshowifconfig(); net_setnetvars(); for (i=0; i<4; i++) ipaddr[i]=tftpipto[i]; for (i=0; i<6; i++) hwaddr[i]=buf->eb_data[6+i]; buf = udp_alloc(); if (!buf) { res = CFE_ERR_TIMEOUT; break; } ebuf_append_u16_be(buf, 3); ebuf_append_u16_be(buf, 1); ebuf_append_bytes(buf,&tftpnull, 0); arp_delete(ipaddr); arp_add(ipaddr,hwaddr); udp_send(info->tftp_socket, buf, tftpipto); } else { for (i=0; i<13; i++) { if (buf->eb_ptr[i] != maclink[i]) break; } if (i==13) { tftpipfrom[0]=buf->eb_ptr[16]; tftpipfrom[1]=buf->eb_ptr[15]; tftpipfrom[2]=buf->eb_ptr[14]; tftpipfrom[3]=buf->eb_ptr[13]; tftpipto[0]=buf->eb_usrptr[0]; tftpipto[1]=buf->eb_usrptr[1]; tftpipto[2]=buf->eb_usrptr[2]; tftpipto[3]=buf->eb_usrptr[3]; net_setparam(NET_IPADDR,tftpipfrom); net_setparam(NET_NETMASK,tftpmask); net_setparam(NET_GATEWAY,tftpipfrom); ui_myshowifconfig(); net_setnetvars(); for (i=0; i<4; i++) ipaddr[i]=tftpipto[i]; for (i=0; i<6; i++) hwaddr[i]=buf->eb_data[6+i]; buf = udp_alloc(); if (!buf) { res = CFE_ERR_TIMEOUT; break; } ebuf_append_u16_be(buf, 3); ebuf_append_u16_be(buf, 1); ebuf_append_bytes(buf,&tftpnull, 0); arp_delete(ipaddr); arp_add(ipaddr,hwaddr); udp_send(info->tftp_socket, buf, tftpipto); } } res = CFE_ERR_TIMEOUT; #else udp_connect(info->tftp_socket,(uint16_t) buf->eb_usrdata); memcpy(info->tftp_ipaddr,buf->eb_usrptr,IP_ADDR_LEN); info->tftp_blknum = 1; info->tftp_blklen = 0; res = 0; #endif break; case TFTP_OP_WRQ: udp_connect(info->tftp_socket,(uint16_t) buf->eb_usrdata); memcpy(info->tftp_ipaddr,buf->eb_usrptr,IP_ADDR_LEN); info->tftp_blknum = 0; res = _tftp_readmore(info); break; default: /* * we aren't expecting any of these messages */ res = CFE_ERR_PROTOCOLERR; break; } udp_free(buf); break; } if (res) { udp_close(info->tftp_socket); info->tftp_socket = -1; } return res; }