/**************************************************************************** ** File: packet_manip.c ** ** Author: Mike Borella ** ** Comments: Packet manipulation routines ** ** $Id: packet_manip.c,v 1.16 2001/10/09 23:20:42 mborella Exp $ ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU Library General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ** *****************************************************************************/ #include "packet_manip.h" #include "hexbuffer.h" extern struct arg_t *my_args; /*---------------------------------------------------------------------------- ** ** get_packet_bytesgeneral() ** ** Non API function, this is a generalization of get_packet_bytes() and ** get_packet_bytestoend(). ** ** Mode 0 is get_packet_bytes() ** Mode 1 is get_packet_bytestoend() ** ** NOTE: This is NOT a safe function. The caller MUST allocate enough memory ** in the destination array. ** ** Returns 0 if operation fails and no write occurs. Returns 1 otherwise. **---------------------------------------------------------------------------- */ inline int get_packet_bytesgeneral(u_int8_t *dst, packet_t *p, unsigned int n, int mode) { /* * First make sure that we can read the bytes without running off the end * of the packet. */ switch(mode) { case 0: if (p->current + n > p->apparent_end + 1) return 0; break; case 1: if (p->current + n > p->end + 1) return 0; break; default: error_message("unknown mode for get_packet_bytesgeneral()"); return 0; } /* * Do the copy */ memcpy(dst, p->current, n); hexbuffer_add(p->current, n); /* * Increment the current pointer */ p->current += n; /* * Return successfully */ return 1; } /*---------------------------------------------------------------------------- ** ** get_packet_bytes() ** ** Grab a specified number of bytes from a packet and deposit them in an array. ** ** NOTE: This is NOT a safe function. The caller MUST allocate enough memory ** in the destination array. ** ** Returns 0 if operation fails and no write occurs. Returns 1 otherwise. **---------------------------------------------------------------------------- */ inline int get_packet_bytes(u_int8_t *dst, packet_t *p, unsigned int n) { return get_packet_bytesgeneral(dst, p, n, 0); } /*---------------------------------------------------------------------------- ** ** get_packet_bytestoend() ** ** Grab a specified number of bytes from a packet and deposit them in an array. ** Get bytes all the way to the real end of the packet, not the apparent end. ** ** NOTE: This is NOT a safe function. The caller MUST allocate enough memory ** in the destination array. ** ** Returns 0 if operation fails and no write occurs. Returns 1 otherwise. **---------------------------------------------------------------------------- */ inline int get_packet_bytestoend(u_int8_t *dst, packet_t *p, unsigned int n) { return get_packet_bytesgeneral(dst, p, n, 1); } /*---------------------------------------------------------------------------- ** ** get_packet_line() ** ** Get a \n terminated line of text from the packet. ** ** NOTE: This is NOT a safe function. The caller MUST allocate enough memory ** in the destination array. ** ** Returns 0 if operation fails and no write occurs. ** Returns number of bytes read otherwise. **---------------------------------------------------------------------------- */ inline int get_packet_line(u_int8_t *dst, u_int32_t max, packet_t *p) { u_int8_t * ptr; int ret; /* * Find the next \n */ ptr = p->current; while (ptr < p->apparent_end && (ptr - p->current) < max - 1) { if (*ptr == '\n') break; ptr++; } /* * If we reached the end, then there's no line to read, fail. */ if (ptr >= p->apparent_end) return 0; /* * Do the copy (NOTE, we do not copy the \n) * We add a \0 in the appropriate place. */ memcpy(dst, p->current, ptr - p->current); dst[ptr - p->current] = '\0'; hexbuffer_add(p->current, ptr - p->current); /* * Increment the current pointer past the \n */ ret = ptr - p->current; p->current += ret + 1; /* * Return successfully the length of the text, not including the \n */ return ret; } /*---------------------------------------------------------------------------- ** ** get_packet_string() ** ** Get a \0 terminated string of text from the packet. ** ** NOTE: This is NOT a safe function. The caller MUST allocate enough memory ** in the destination array. ** ** Returns 0 if operation fails and no write occurs. ** Returns number of bytes read otherwise. **---------------------------------------------------------------------------- */ inline int get_packet_string(u_int8_t *dst, u_int32_t max, packet_t *p) { u_int8_t * ptr; int ret; /* * Find the next \0 */ ptr = p->current; while (ptr < p->apparent_end && (ptr - p->current) < max - 1) { if (*ptr == '\0') break; ptr++; } /* * If we reached the end, then there's no line to read, fail. */ if (ptr >= p->apparent_end) return 0; /* * Do the copy (NOTE, we do not copy the \0) * We add a \0 in the appropriate place. */ memcpy(dst, p->current, ptr - p->current); dst[ptr - p->current] = '\0'; hexbuffer_add(p->current, ptr - p->current); /* * Increment the current pointer past the \0 */ ret = ptr - p->current; p->current += ret + 1; /* * Return successfully the length of the text */ return ret; } /*---------------------------------------------------------------------------- ** ** look_packet_bytes() ** ** Copy specified number of bytes from a packet and deposit them in an array. ** Unlike get_packet_bytes(), we will not increment the pointer. ** ** NOTE: This is NOT a safe function. The caller MUST allocate enough memory ** in the destination array. ** ** Returns 0 if operation fails and no write occurs. Returns 1 otherwise. **---------------------------------------------------------------------------- */ inline int look_packet_bytes(u_int8_t *dst, packet_t *p, unsigned int n) { /* * First make sure that we can read the bytes without running off the end * of the packet. */ if (p->current + n > p->apparent_end + 1) return 0; /* * Do the copy */ memcpy(dst, p->current, n); /* * Return successfully */ return 1; } /*---------------------------------------------------------------------------- ** ** skip_packet_bytes() ** ** Jump the pointer ahead the specified number of bytes ** ** Returns 0 if operation fails and no write occurs. Returns 1 otherwise. **---------------------------------------------------------------------------- */ inline int skip_packet_bytes(packet_t *p, unsigned int n) { /* * First make sure that we can read the bytes without running off the end * of the packet. */ if (p->current + n > p->apparent_end + 1) return 0; /* * Increment the current pointer */ p->current += n; hexbuffer_add(p->current, n); /* * Return successfully */ return 1; } /*---------------------------------------------------------------------------- ** ** skip_packet_toapparentend() ** ** Jump the pointer ahead the apparent end of the packet. Useful for ** jumping a padding section, if one exists. ** ** Returns 0 if operation fails and no write occurs. Returns 1 otherwise. **---------------------------------------------------------------------------- */ inline int skip_packet_toapparentend(packet_t *p) { if (p->current > p->apparent_end) return 0; /* * Set the current pointer */ p->current = p->apparent_end; /* * Return successfully */ return 1; } /*---------------------------------------------------------------------------- ** ** get_packet_apparentbytesleft() ** ** Returns the # of apparent bytes left to read off of the packet. ** **---------------------------------------------------------------------------- */ inline u_int32_t get_packet_apparentbytesleft(packet_t *pkt) { u_int32_t len; len = pkt->apparent_end - pkt->current; if (len < 0) return 0; else return len; } /*---------------------------------------------------------------------------- ** ** get_packet_bytesleft() ** ** Returns the # of bytes left to read off of the packet. ** **---------------------------------------------------------------------------- */ inline u_int32_t get_packet_bytesleft(packet_t *pkt) { u_int32_t len; len = pkt->end - pkt->current; if (len < 0) return 0; else return len; } /*---------------------------------------------------------------------------- ** ** packet_haspadding() ** ** Returns 1 if there are bytes between the apparent end and the real end, ** 0 otherwise ** **---------------------------------------------------------------------------- */ inline int packet_haspadding(packet_t *pkt) { u_int32_t len; len = pkt->end - pkt->apparent_end; if (len <= 0) return 0; else return 1; } /*---------------------------------------------------------------------------- ** ** set_packet_mark() ** ** Mark the current byte of the packet ** **---------------------------------------------------------------------------- */ inline void set_packet_mark(packet_t *pkt) { pkt->mark = pkt->current; } /*---------------------------------------------------------------------------- ** ** get_packet_markdistance() ** ** Get the distance between the current pointer and the mark ** **---------------------------------------------------------------------------- */ inline int32_t get_packet_markdistance(packet_t *pkt) { /* * Sanity check the mark first */ if (pkt->mark < pkt->contents || pkt->mark > pkt->apparent_end) return -1; return pkt->current - pkt->mark; } /*---------------------------------------------------------------------------- ** ** set_packet_apparentend() ** ** Set the apparent end of the packet to be the given number of bytes beyond ** the current pointer. ** **---------------------------------------------------------------------------- */ inline void set_packet_apparentend(packet_t * pkt, int n) { /* make sure we're not running off the packet */ if (pkt->current + n >= pkt->apparent_end) return; pkt->apparent_end = pkt->current + n; }