📄 dhcp-option-convert.c
字号:
/* $Header: /cvsroot/dhcp-agent/dhcp-agent/src/dhcp-option-convert.c,v 1.6 2003/06/27 03:16:27 actmodern Exp $ * * Copyright 2002, 2003 Thamer Alharbash <tmh@whitefang.com> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * 3. The names of the authors may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * *//* FIXME: still a tad messy and a bit over redundant. but it * works for now until release time. document and prune anything * that needs pruning. */#define MODULE_NAME "dhcp-option-convert"#include "dhcp-local.h"#include "dhcp-libutil.h"#include "dhcp-librawnet.h"#include "dhcp-option.h"#include "dhcp-option-convert.h"#include "dhcp-limits.h"/* * * * * * * * * * utility routines. * * * * * * * * * * * * *//* count internal string atoms, and mark with sentinals. this * wrecks the string so it should only be used on a copy. * FIXME: this works but really should be a stringbuffer thing. */static size_t count_internal_string_atoms_and_mark(char *input){ char *ptr; size_t num = 0; ptr = input; while(*ptr) { switch(*ptr) { case ';': num++; *ptr = 0; ptr++; case '\\': if((*ptr + 1) == ';') { ptr += 2; /* skip. */ } default: /* fall through. */ ptr++; break; } } if(num == 0 && *input != 0) num++; /* we have at least one. */ return num;}/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * From internal to network format: * * * * * * uint8, int8 are just copied verbatim since they're octets * * which need no marshalling. * * * * uint16, int16 are htons as they are copied over. * * * * uint32, int32 are htonl as they are copied over. * * * * signed are wrapped around unsigned conversions since * * marshalling should not interfere with signedness. * * * * copying from a list is a bit more ugly. here we redo * * everything only we're copying from a list to contigenous * * memory. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//* make a copy of an unsigned byte. */static uint8_t *uint8_copy_to_network(const void *data, size_t num){ uint8_t *uint8_copy; uint8_copy = xmalloc((sizeof(uint8_t) * num)); memcpy(uint8_copy, data, (sizeof(uint8_t) * num)); return uint8_copy;}/* make a copy of an signed byte. */static int8_t *int8_copy_to_network(const void *data, size_t num){ return (int8_t *)uint8_copy_to_network(data, num); /* just cast. since it doesn't matter. */}/* make a copy of an unsigned 16-bit integer to network. */static uint16_t *uint16_copy_to_network(const void *data, size_t num){ const uint16_t *uint16_data; uint16_t *uint16_copy; size_t i; uint16_data = data; uint16_copy = xmalloc((sizeof(uint16_t) * num)); for(i = 0;i < num;i ++) { uint16_copy[i] = htons(uint16_data[i]); } return uint16_copy;}/* make a copy of an signed 16-bit integer. */static int16_t *int16_copy_to_network(const void *data, size_t num){ /* just cast. since it doesn't matter as long as we're just copying. */ return (int16_t *)uint16_copy_to_network(data, num);}/* make a copy of an unsigned 32-bit integer. */static uint32_t *uint32_copy_to_network(const void *data, size_t num){ const uint32_t *uint32_data; uint32_t *uint32_copy; size_t i; uint32_data = data; uint32_copy = xmalloc((sizeof(uint32_t) * num)); for(i = 0;i < num;i ++) { uint32_copy[i] = htonl(uint32_data[i]); } return uint32_copy;}/* make a copy of an signed 16-bit integer. */static int32_t *int32_copy_to_network(const void *data, size_t num){ /* just cast. since it doesn't matter as long as we're just copying. */ return (int32_t *)uint32_copy_to_network(data, num); }static void *int_list_copy_to_network(list_t *list, size_t size, uint8_t sign){ void *datum; void *ret_data; size_t num; /* get rid of compiler warnings. these will be initialized but the compiler may not see it .*/ uint8_t *uint8_data = NULL; uint16_t *uint16_data = NULL; uint32_t *uint32_data = NULL; int8_t *int8_data = NULL; int16_t *int16_data = NULL; int32_t *int32_data = NULL; uint8_t *uint8_ptr = NULL; uint16_t *uint16_ptr = NULL; uint32_t *uint32_ptr = NULL; int8_t *int8_ptr = NULL; int16_t *int16_ptr = NULL; int32_t *int32_ptr = NULL; num = list_get_len(list); /* create datum. it's size * num, but we need to assign it to the right pointer. */ if(sign) { switch(size) { case sizeof(int8_t): int8_data = xmalloc(sizeof(int8_data) * num); int8_ptr = int8_data; ret_data = int8_data; break; case sizeof(int16_t): int16_data = xmalloc(sizeof(int16_data) * num); int16_ptr = int16_data; ret_data = int16_data; break; case sizeof(int32_t): int32_data = xmalloc(sizeof(int32_data) * num); int32_ptr = int32_data; ret_data = int32_data; break; default: FATAL_MESSAGE("illegal size passed for conversion. this is a bug report me."); exit(1); } } else { switch(size) { case sizeof(uint8_t): uint8_data = xmalloc(sizeof(uint8_t) * num); uint8_ptr = uint8_data; ret_data = uint8_data; break; case sizeof(uint16_t): uint16_data = xmalloc(sizeof(uint16_t) * num); uint16_ptr = uint16_data; ret_data = uint16_data; break; case sizeof(uint32_t): uint32_data = xmalloc(sizeof(uint32_t) * num); uint32_ptr = uint32_data; ret_data = uint32_data; break; default: FATAL_MESSAGE("illegal size passed for conversion. this is a bug report me."); exit(1); } } while((datum = list_next(list)) != NULL) { if(sign) { switch(size) { case sizeof(int8_t): *int8_ptr = *(int8_t *)datum; int8_ptr++; break; case sizeof(int16_t): *int16_ptr = htons(*(int16_t *)datum); int16_ptr++; break; case sizeof(int32_t): memcpy(int32_ptr, datum, sizeof(int32_t)); *int32_ptr = htons(*(int32_t *)datum); int32_ptr++; break; default: FATAL_MESSAGE("illegal size passed for conversion. this is a bug report me."); exit(1); } } else { switch(size) { case sizeof(uint8_t): memcpy(uint8_ptr, datum, sizeof(uint8_t)); uint8_ptr++; break; case sizeof(uint16_t): *uint16_ptr = htons(*(uint16_t *)datum); uint16_ptr++; break; case sizeof(uint32_t): *uint32_ptr = htons(*(uint32_t *)datum); uint32_ptr++; break; default: FATAL_MESSAGE("illegal size passed for conversion. this is a bug report me."); exit(1); } } } return ret_data;}/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * From network to internal format: * * * * uint8, int8 are just copied verbatim since they're octets * * which need no marshalling. we can call the uint8 * * copy to network routines since they do the same thing. * * * * uint16, int16 are ntohs as they are copied over. * * * * uint32, int32 are ntohl as they are copied over. * * * * signed conversions are wrapped around unsigned conversions * * since marshalling should not interfere with signedness. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//* make a copy of an unsigned byte from network. */static uint8_t *uint8_copy_from_network(const uint8_t *data, size_t num){ /* no marshalling needs to be done on individual bytes. */ return uint8_copy_to_network(data, num);}/* make a copy of an signed byte from network. */static int8_t *int8_copy_from_network(const uint8_t *data, size_t num){ /* no marshalling needs to be done on individual bytes. */ return int8_copy_to_network(data, num);}/* make a copy of an unsigned 16-bit integer from network. */static uint16_t *uint16_copy_from_network(const void *data, size_t num){ const uint16_t *uint16_data; uint16_t *uint16_copy; size_t i; uint16_copy = xmalloc((sizeof(uint16_t) * num)); uint16_data = data; for(i = 0;i < num;i ++) { uint16_copy[i] = ntohs(uint16_data[i]); } return uint16_copy;}/* make a copy of an signed 16-bit integer. */static int16_t *int16_copy_from_network(const void *data, size_t num){ /* just cast. since it doesn't matter as long as we're just copying. */ return (int16_t *)uint16_copy_from_network(data, num);}/* make a copy of an unsigned 32-bit integer. */static uint32_t *uint32_copy_from_network(const void *data, size_t num){ const uint32_t *uint32_data = data; uint32_t *uint32_copy; size_t i; uint32_copy = xmalloc((sizeof(uint32_t) * num)); uint32_data = data; for(i = 0;i < num;i ++) { uint32_copy[i] = ntohl(uint32_data[i]); } return uint32_copy;}/* make a copy of an signed 16-bit integer. */static int32_t *int32_copy_from_network(const void *data, size_t num){ /* just cast. since it doesn't matter as long as we're just copying. */ return (int32_t *)uint32_copy_to_network(data, num); }/* convenience routine. take any size/typ eand convert to a list. */static list_t *int_list_from_network_proc(const uint8_t *data, size_t len, size_t size, uint8_t sign){ list_t *data_list; void *datum; /* check for at least one atom. */ if(len < size) return NULL; /* check to make sure it's divisible by exactly the size of the atom. */ if(len%size) return NULL; data_list = list_create(); while(len) { if(sign) { switch(size) { case sizeof(int8_t): datum = int8_copy_from_network(data, 1); break; case sizeof(int16_t): datum = int16_copy_from_network(data, 1); break; case sizeof(int32_t): datum = int32_copy_from_network(data, 1); break; default: FATAL_MESSAGE("illegal size passed for conversion. this is a bug report me."); exit(1); } } else { switch(size) { case sizeof(uint8_t): datum = uint8_copy_from_network(data, 1); break; case sizeof(uint16_t): datum = uint16_copy_from_network(data, 1); break; case sizeof(uint32_t): datum = uint32_copy_from_network(data, 1); break; default: FATAL_MESSAGE("illegal size passed for conversion. this is a bug report me."); exit(1); } } if(datum == NULL) { list_destroy(data_list, xfree); return NULL; } /* add datum to list. */ list_add(data_list, datum); /* decrement length, and push pointer forward. */ len -= size; data += size; } return data_list;}/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * From internal string to internal format. * * * * All input is passed via a string. The string is re-read from * * a file we've already created (usually), or rewritten to be * * handled internally. This means we can trust it. * * * * scanfs throughout with the necessary C99 macro to read * * in the value. * * * * The only special case happens when we want to read into a * * list or an array. Here we expect a string with null * * characters to terminate the individual datums. This is done * * by marking the special delimiter ';'. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//* internal string to internal unsigned byte value. */static uint8_t *internal_string_uint8_to_internal(const char *input){ uint8_t *uint8_val; uint8_val = xmalloc(sizeof(uint8_t)); sscanf(input, "%"SCNu8, uint8_val); return uint8_val;}/* internal string to internal unsigned byte value. */static uint16_t *internal_string_uint16_to_internal(const char *input){ uint16_t *uint16_data; uint16_data = xmalloc(sizeof(uint16_t)); sscanf(input, "%"SCNu16, uint16_data); return uint16_data;}/* internal string to internal unsigned byte value. */static uint32_t *internal_string_uint32_to_internal(const char *input){ uint32_t *uint32_data; uint32_data = xmalloc(sizeof(uint32_t)); sscanf(input, "%"SCNu32, uint32_data); return uint32_data;}/* internal string to internal signed 8-bit value. */static int8_t *internal_string_int8_to_internal(const char *input){ int8_t *int8_val; int8_val = xmalloc(sizeof(int8_t)); sscanf(input, "%"SCNi8, int8_val); return int8_val;}/* internal string to internal byte value. */static int16_t *internal_string_int16_to_internal(const char *input){ int16_t *int16_val; int16_val = xmalloc(sizeof(int16_t)); sscanf(input, "%"SCNi16, int16_val); return int16_val;}/* internal string to internal byte value. */static int32_t *internal_string_int32_to_internal(const char *input){ int32_t *int32_val; int32_val = xmalloc(sizeof(int32_t)); sscanf(input, "%"SCNi32, int32_val); return int32_val;}/* * * * * * * * * * * * * * * * * * * * internal string to integer array. * * * * * * * * * * * * * * * * * * * */static void *internal_string_to_array_int_proc(const char *input, size_t count, size_t size, uint8_t sign){ void *data; size_t i; const char *ptr; uint8_t *uint8_ptr; uint16_t *uint16_ptr; uint32_t *uint32_ptr; int8_t *int8_ptr; int16_t *int16_ptr; int32_t *int32_ptr; data = xmalloc(count * size); ptr = input; i = 0; while(i < count) { if(sign) { switch(size) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -