File: rip.c

package info (click to toggle)
sendip 2.6-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, sid, trixie
  • size: 484 kB
  • sloc: ansic: 3,737; perl: 321; makefile: 55; sh: 13
file content (135 lines) | stat: -rw-r--r-- 4,435 bytes parent folder | download
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;
}