📄 tftp.c
字号:
display_dns_error(session->sty, query, error); /* Give the terminal back. */ sty_read(session->sty, do_cmd, prompt, 0); tftp_exit(session);}/* tftp_dns_won() * * DNS callback if it got an IP address * * goes ahead and starts up the TFTP transfer */static void tftp_dns_won(struct dns_query *query, char *dname, int n, ipaddr_t addrs[], void *cookie){ struct tftp_state * session = (struct tftp_state *) cookie; char * filename_bare; char * filename_index; char * mode;#if INSTALL_SNARK_ATTACHE_34_TFTP_COMPAT inaddr_t oldaddr;#endif /* stick the IP address into our state block */ IPADDR_COPY(&session->host, &addrs[0]); /* strip down the filename so we open it in the current directory */ for (filename_bare = filename_index = session->file_name_ptr; *filename_index; filename_index++) { if (*filename_index == '/') filename_bare = filename_index+1;#if INSTALL_on_msdos else if (*filename_index == '\\') filename_bare = filename_index+1;#endif } /* open up the local file */ if (session->direction == 1) mode = "wb"; else mode = "rb"; session->fp = fopen(filename_bare, mode); if (session->fp == 0) { sty_printf(session->sty, "%% Couldn't open %s for writing\n", filename_bare); tftp_exit(session); /* Give the terminal back. * Makes ownership fuzzy, but that's the way to do parallel transfers. */ sty_read(session->sty, do_cmd, prompt, 0); return; } /* We have a valid state block. Link it in. */ session->next = tftp_state_head; tftp_state_head = session;#if INSTALL_SNARK_ATTACHE_34_TFTP_COMPAT if (!newapi) { if (GET_IPADDR_TYPE(&session->host) != IPV4) { sty_printf(session->sty, "%% Can't do non-IPV4 TFTP through old API; try reconfiguring .."); tftp_exit(session); /* Give the terminal back. * Makes ownership fuzzy, but that's the way to do parallel transfers. */ sty_read(session->sty, do_cmd, prompt, 0); return; } MEMCPY(&oldaddr, PTR_IPADDR_BITS(&session->host), IPV4_ADDR_LEN); if (session->direction == 1) session->cnxn = tftpc_getfile(oldaddr, session->file_name_ptr, MODE_OCTET, tftp_read_handler, (void *) session);#if INSTALL_ATTACHE_TFTP_SENDFILE else session->cnxn = tftpc_sendfile(oldaddr, session->file_name_ptr, MODE_OCTET, tftp_write_handler, (void *) session);#endif /* TFTP_SENDFILE */ } else #endif /* TFTP_COMPAT */ { if (session->direction == 1) session->cnxn = tftpc_fetchfile(&session->host, session->file_name_ptr, MODE_OCTET, tftp_read_handler, (void *) session);#if INSTALL_ATTACHE_TFTP_SENDFILE else session->cnxn = tftpc_putfile(&session->host, session->file_name_ptr, MODE_OCTET, tftp_write_handler, (void *) session);#endif /* TFTP_SENDFILE */ } sty_printf(session->sty, "tftp %s of %s %s host %s (%s) started\n", session->direction?"fetch":"store", session->file_name_ptr, session->direction?"from":"to", dname, ipaddr_to_string(&addrs[0], 0, 0)); /* Give the terminal back. * Makes ownership fuzzy, but that's the way to do parallel transfers. */ sty_read(session->sty, do_cmd, prompt, 0);}/* tftp_exit() * * call this to delete the session structure and generally clean * up when you're done with tftp * * returns TRUE if it finds a problem, FALSE otherwise */static boolean_t tftp_exit(struct tftp_state * session){ struct tftp_state **p = &tftp_state_head; while (*p && *p != session) p = &(*p)->next; if (*p == 0) return TRUE; *p = session->next; if (session->fp) fclose(session->fp); if (session->file_name_ptr) { sty_printf(session->sty, "\nDone with tftp %s of %s\n", ((session->direction == 2) ? "send" : "get"), session->file_name_ptr); GLUE_FREE(session->file_name_ptr); } GLUE_FREE(session); return FALSE;}/* tftp_error_print() * * print out the appropriate error message; give it a table of tftp_err_lookup * structures and the error value to match for, and it will find the * appropriate string from the table and print it out. */static boolean_t tftp_error_print(struct sty * sty, struct tftp_err_lookup table[], int table_size, int err_val){ int i; for (i=0; i< table_size; i++) { if (table[i].err_code == err_val) { sty_printf(sty, "%s\n", table[i].err_string); return TRUE; } } sty_puts(sty, "unknown error\n"); return FALSE;}static void tftp_read_delack_handler(struct timer *tm, void *cookie){ struct tftp_state *xfer = cookie; packet *pkt = xfer->delay_pkt; xfer->delay_pkt = NULL; if (fwrite(pkt->pkt_data, 1, pkt->pkt_datalen, xfer->fp) == pkt->pkt_datalen) { udp_free(pkt); }#ifdef TFTP_DEBUG sty_printf(xfer->sty, "delack %d\n", xfer->delay_block);#endif tftpc_sendack(xfer->cnxn, xfer->delay_block); if (xfer->defer_exit) tftp_exit(xfer);}/* tftp_read_handler() * * callback function for tftp reads */static int tftp_read_handler (tftp_rval_t code, packet *pkt, void *cookie, tftp_error_t errnum, tftp_cnxn_t * tftp_cnxn){ struct tftp_state * xfer = (struct tftp_state *) cookie; int retval = TFTP_ERROR; switch (code) { case HND_ERROR: tftp_error_print(xfer->sty, tftp_err_strings, TFTP_ERR_STRINGS, errnum); if (pkt && pkt->pkt_data) /* RFC-1350 says the error string is null-terminated. */ sty_puts(xfer->sty, (char *) (pkt->pkt_data)); break; case HND_DONE: if (xfer->delay_pkt) { xfer->defer_exit = 1; return TFTP_GOOD; } else { fclose(xfer->fp); } retval = TFTP_GOOD; break; case HND_DATA: if (!delack) { if (fwrite(pkt->pkt_data, 1, pkt->pkt_datalen, xfer->fp) == pkt->pkt_datalen) { udp_free(pkt); return TFTP_GOOD; /* The write was OK. */ } } else { if (xfer->delay_pkt) { sty_printf(xfer->sty, "We already have a delayed packet.. oops, blowing up connection\n"); return TFTP_ERROR; } xfer->delay_pkt = pkt; xfer->delay_block = tftp_cnxn_get_blocknum(tftp_cnxn); etc_tm_set(&xfer->delack_tm, 100); /* 100ms */ return TFTP_WAIT; } /* If we got here, there were problems with the write. */ sty_puts(xfer->sty, "Problem writing to file.\n"); break; } if (tftp_exit(xfer)) retval = TFTP_ERROR; /* TFTP module thinks we're responsible for freeing the packet... */ if (pkt != 0) udp_free(pkt); return retval;}#if INSTALL_ATTACHE_TFTP_SENDFILE /* tftp_write_handler() * * callback function for tftp write */static int tftp_write_handler (tftp_rval_t code, packet *pkt, void *cookie, tftp_error_t errnum, tftp_cnxn_t * tftp_cnxn){ struct tftp_state * xfer = (struct tftp_state *) cookie; int retval = -1; int bytes_read; switch (code) { case HND_ERROR: tftp_error_print(xfer->sty, tftp_err_strings, TFTP_ERR_STRINGS, errnum); if (pkt && pkt->pkt_data) /* RFC-1350 says the error string is null-terminated. */ sty_puts(xfer->sty, (char *) (pkt->pkt_data)); break; case HND_DONE: fclose(xfer->fp); retval = 0; break; case HND_DATA: bytes_read = fread(pkt->pkt_data, 1, pkt->pkt_datalen, xfer->fp); if ((bytes_read != pkt->pkt_datalen) && (!feof(xfer->fp)) ) return -1; else { pkt->pkt_datalen = bytes_read; return 1; } } if (tftp_exit(xfer)) retval = -1; return retval;}#endif/* tftp_parse_parm() * * Parse a parameter to a command. * * Takes a string containing the parameter entered, * a list of possible parameter values to match it against, * and a count of the number of values in that list. * Returns the 1-based offset of the matched value, * or 0 if not found. */static int tftp_parse_parm(char * cmd, char * cmd_list[], int num_choices){ int i; if (cmd == NULL) return 0; for (i=0; i<num_choices; i++) if (STRNICMP(cmd, cmd_list[i], strlen(cmd)) == 0) return (i+1); return 0;}#endif /* INSTALL_ATTACHE_DNS && INSTALL_ATTACHE_TFTP */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -