1 /* ripng.c - RIPng (version 1) code for sendip
2 * Created by hacking rip code
3 * ChangeLog since 2.2 release:
4 * 15/10/2002 Read the spec
5 * 24/11/2002 Made it compile on archs needing alignment
6 */
7
8 #include <stdlib.h>
9 #include <sys/types.h>
10 #include <sys/socket.h>
11 #include <netinet/in.h>
12 #include <arpa/inet.h>
13 #include <netdb.h>
14 #include <string.h>
15 #include "sendip_module.h"
16 #include "ripng.h"
17
18 /* Character that identifies our options
19 */
20 const char opt_char='R';
21
inet6_addr(char * hostname)22 static struct in6_addr inet6_addr(char *hostname) {
23 struct hostent *host = gethostbyname2(hostname,AF_INET6);
24 struct in6_addr ret;
25 if(host==NULL) {
26 fprintf(stderr,"RIPNG: Couldn't get address for %s defaulting to loopback",hostname);
27 return in6addr_loopback;
28 }
29 if(host->h_length != sizeof(struct in6_addr)) {
30 fprintf(stderr,"RIPNG: IPV6 address is the wrong size: defaulting to loopback");
31 return in6addr_loopback;
32 }
33 memcpy(&ret,host->h_addr,sizeof(ret));
34 return ret;
35 }
36
initialize(void)37 sendip_data *initialize(void) {
38 sendip_data *ret = malloc(sizeof(sendip_data));
39 ripng_header *rip = malloc(sizeof(ripng_header));
40 memset(rip,0,sizeof(ripng_header));
41 ret->alloc_len = sizeof(ripng_header);
42 ret->data = (void *)rip;
43 ret->modified=0;
44 return ret;
45 }
46
do_opt(char * opt,char * arg,sendip_data * pack)47 bool do_opt(char *opt, char *arg, sendip_data *pack) {
48 ripng_header *rippack = (ripng_header *)pack->data;
49 ripng_entry *ripopt;
50 char *p, *q;
51 switch(opt[1]) {
52 case 'v': /* version */
53 rippack->version = (u_int8_t)strtoul(arg, (char **)0, 0);
54 pack->modified |= RIPNG_MOD_VERSION;
55 break;
56 case 'c': /* command */
57 rippack->command = (u_int8_t)strtoul(arg, (char **)0, 0);
58 pack->modified |= RIPNG_MOD_COMMAND;
59 break;
60 case 'r': /* reserved */
61 rippack->res = htons((u_int16_t)strtoul(arg, (char **)0, 0));
62 pack->modified |= RIPNG_MOD_RESERVED;
63 break;
64 /*
65 case 'a': / * authenticate * /
66 if(RIPNG_NUM_ENTRIES(pack) != 0) {
67 usage_error("Warning: a real RIP-2 packet only has authentication on the first entry.\n");
68 }
69 pack->modified |= RIP_IS_AUTH;
70 pack->data = realloc(pack->data,pack->alloc_len+strlen(arg));
71 strcpy(pack->data+pack->alloc_len,arg);
72 pack->alloc_len += strlen(arg);
73 break;
74 */
75 case 'e': /* rip entry */
76 RIPNG_ADD_ENTRY(pack);
77 ripopt = RIPNG_ENTRY(pack);
78 p=q=arg;
79 /* TODO: if arg is malformed, this could segfault */
80 while(*(q++)!='/') /* do nothing */; *(--q)='\0';
81 ripopt->prefix = (p==q)?in6addr_any:inet6_addr(p);
82
83 p=++q; while(*(q++)!='/') /* do nothing */; *(--q)='\0';
84 ripopt->tag=htons( (p==q)?0:(u_int16_t)strtoul(p, (char **)0,0));
85
86 p=++q; while(*(q++)!='/') /* do nothing */; *(--q)='\0';
87 ripopt->len=(p==q)?(u_int8_t)128:(u_int8_t)strtoul(p, (char **)0,0);
88
89 p=++q; while(*(q++)!='\0') /* do nothing */; *(--q)='\0';
90 ripopt->metric=(p==q)?(u_int8_t)16:(u_int8_t)strtoul(p,(char **)0, 0);
91 break;
92 case 'd': /* default request */
93 if(RIPNG_NUM_ENTRIES(pack) != 0) {
94 usage_error("Warning: a real RIPng packet does not have any other entries in a default request.\n");
95 }
96 rippack->command = (u_int8_t)1;
97 rippack->version = (u_int8_t)1;
98 rippack->res = (u_int16_t)0;
99 pack->modified|=RIPNG_MOD_COMMAND|RIPNG_MOD_VERSION|RIPNG_MOD_RESERVED;
100 RIPNG_ADD_ENTRY(pack);
101 ripopt=RIPNG_ENTRY(pack);
102 ripopt->prefix=in6addr_any;
103 ripopt->tag=(u_int16_t)0;
104 ripopt->len=(u_int8_t)0;
105 ripopt->metric=htons((u_int16_t)16);
106 break;
107 }
108 return TRUE;
109
110 }
111
finalize(char * hdrs,sendip_data * headers[],sendip_data * data,sendip_data * pack)112 bool finalize(char *hdrs, sendip_data *headers[], sendip_data *data,
113 sendip_data *pack) {
114 if(hdrs[strlen(hdrs)-1] != 'u') {
115 usage_error("Warning: RIPng should be contained in a UDP packet\n");
116 }
117
118 return TRUE;
119 }
120
num_opts()121 int num_opts() {
122 return sizeof(rip_opts)/sizeof(sendip_option);
123 }
get_opts()124 sendip_option *get_opts() {
125 return rip_opts;
126 }
get_optchar()127 char get_optchar() {
128 return opt_char;
129 }
130