1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
|
/* rip.c - RIP-1 and -2 code for sendip
* Taken from code by Richard Polton <Richard.Polton@msdw.com>
* ChangeLog since 2.0 release:
* 02/12/2001 Only check 1 layer for enclosing UDP header
* 21/08/2002 Off-by-one fix in -re handling that caused bad things to happen
* 21/08/2002 htons() and htonl() added where needed
* ChangeLog since 2.2 release:
* 24/11/2002 make it compile on archs that care about alignment
* ChangeLog since 2.5 release:
* 26/10/2004 fix bug with multiple -re options (found by several people)
* 28/10/2004 fix -ra (thanks to sharmily.anantaraman@conexant.com)
*/
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include "sendip_module.h"
#include "rip.h"
/* Character that identifies our options
*/
const char opt_char='r';
sendip_data *initialize(void) {
sendip_data *ret = malloc(sizeof(sendip_data));
rip_header *rip = malloc(sizeof(rip_header));
memset(rip,0,sizeof(rip_header));
ret->alloc_len = sizeof(rip_header);
ret->data = (void *)rip;
ret->modified=0;
return ret;
}
bool do_opt(char *opt, char *arg, sendip_data *pack) {
rip_header *rippack = (rip_header *)pack->data;
rip_options *ripopt;
char *p, *q;
int l;
switch(opt[1]) {
case 'v': /* version */
rippack->version = (u_int8_t)strtoul(arg, (char **)0, 0);
pack->modified |= RIP_MOD_VERSION;
break;
case 'c': /* command */
rippack->command = (u_int8_t)strtoul(arg, (char **)0, 0);
pack->modified |= RIP_MOD_COMMAND;
break;
case 'a': /* authenticate */
if(RIP_NUM_ENTRIES(pack) != 0) {
usage_error("Warning: a real RIP-2 packet only has authentication as the first entry.\n");
}
RIP_ADD_ENTRY(pack);
ripopt = RIP_OPTION(pack);
memset(ripopt,0,sizeof(rip_options));
ripopt->addressFamily=0xFFFF;
p=q=arg;
/* TODO: if arg is malformed, this could segfault */
while(*(q++)!=':') {} /* do nothing */; *(--q)='\0';
ripopt->routeTagOrAuthenticationType=htons((p==q)?2:(u_int16_t)strtoul(p, (char **)0,0));
p=++q;
l=strlen(p)+1;
if(l > 16) {
usage_error("Warning: RIP password cannot be longer than 16 characters.\n");
l=16;
}
memcpy((char *)&(ripopt->address), p, l);
break;
case 'e': /* rip entry */
if(RIP_NUM_ENTRIES(pack)==25) {
usage_error("Warning: a real RIP packet contains no more than 25 entries.\n");
}
RIP_ADD_ENTRY(pack);
ripopt = RIP_OPTION(pack);
p=q=arg;
/* TODO: if arg is malformed, this could segfault */
while(*(q++)!=':') {} /* do nothing */; *(--q)='\0';
ripopt->addressFamily= htons((p==q)?2:(u_int16_t)strtoul(p, (char **)0, 0));
p=++q; while(*(q++)!=':') {} /* do nothing */; *(--q)='\0';
ripopt->routeTagOrAuthenticationType=htons((p==q)?0:(u_int16_t)strtoul(p, (char **)0,0));
p=++q; while(*(q++)!=':') {} /* do nothing */; *(--q)='\0';
ripopt->address=(p==q)?inet_addr("0.0.0.0"):inet_addr(p);
p=++q; while(*(q++)!=':') {} /* do nothing */; *(--q)='\0';
ripopt->subnetMask=(p==q)?inet_addr("255.255.255.0"):inet_addr(p);
p=++q; while(*(q++)!=':') {} /* do nothing */; *(--q)='\0';
ripopt->nextHop=(p==q)?inet_addr("0.0.0.0"):inet_addr(p);
p=++q; while(*(q++)!='\0') {} /* do nothing */; *(--q)='\0';
ripopt->metric=htonl((p==q)?16:(u_int32_t)strtoul(p,(char **)0, 0));
break;
case 'd': /* default request */
if(RIP_NUM_ENTRIES(pack) != 0) {
usage_error("Warning: a real RIP-1 or -2 packet does not have any entries in a default request.\n");
}
RIP_ADD_ENTRY(pack);
ripopt=RIP_OPTION(pack);
rippack->command = (u_int8_t)1;
ripopt->addressFamily = (u_int16_t)0;
ripopt->routeTagOrAuthenticationType = (u_int16_t)0;
ripopt->address=inet_addr("0.0.0.0");
ripopt->subnetMask=inet_addr("0.0.0.0");
ripopt->nextHop=inet_addr("0.0.0.0");
ripopt->metric=htons((u_int16_t)16);
break;
case 'r': /* set reserved field */
rippack->res = (u_int16_t)strtoul(arg, (char **)0, 0);
pack->modified |= RIP_MOD_RESERVED;
break;
default:
usage_error("Unrecognized option opt");
return FALSE;
}
return TRUE;
}
bool finalize(char *hdrs, sendip_data *headers[], sendip_data *data,
sendip_data *pack) {
if(hdrs[strlen(hdrs)-1] != 'u') {
usage_error("Warning: RIP should be contained in a UDP packet\n");
}
return TRUE;
}
int num_opts() {
return sizeof(rip_opts)/sizeof(sendip_option);
}
sendip_option *get_opts() {
return rip_opts;
}
char get_optchar() {
return opt_char;
}
|