| |
1 /* This file is part of the Project Athena Zephyr Notification System. |
| |
2 * It contains source for the ZParseNotice function. |
| |
3 * |
| |
4 * Created by: Robert French |
| |
5 * |
| |
6 * $Source$ |
| |
7 * $Author: warmenhoven $ |
| |
8 * |
| |
9 * Copyright (c) 1987,1991 by the Massachusetts Institute of Technology. |
| |
10 * For copying and distribution information, see the file |
| |
11 * "mit-copyright.h". |
| |
12 */ |
| |
13 /* $Header$ */ |
| |
14 |
| |
15 #ifndef lint |
| |
16 static char rcsid_ZParseNotice_c[] = |
| |
17 "$Zephyr: /mit/zephyr/src/lib/RCS/ZParseNotice.c,v 1.22 91/03/29 03:34:46 raeburn Exp $"; |
| |
18 #endif |
| |
19 |
| |
20 #include <internal.h> |
| |
21 |
| |
22 /* Assume that strlen is efficient on this machine... */ |
| |
23 #define next_field(ptr) ptr += strlen (ptr) + 1 |
| |
24 |
| |
25 #if defined (__GNUC__) && defined (__vax__) |
| |
26 #undef next_field |
| |
27 static __inline__ char * Istrend (char *str) { |
| |
28 /* |
| |
29 * This should be faster on VAX models outside the 2 series. Don't |
| |
30 * use it if you are using MicroVAX 2 servers. If you are using a |
| |
31 * VS2 server, use something like |
| |
32 * #define next_field(ptr) while(*ptr++) |
| |
33 * instead of this code. |
| |
34 * |
| |
35 * This requires use of GCC to get the optimized code, but |
| |
36 * everybody uses GCC, don't they? :-) |
| |
37 */ |
| |
38 register char *str2 asm ("r1"); |
| |
39 /* Assumes that no field is longer than 64K.... */ |
| |
40 asm ("locc $0,$65535,(%1)" : "=r" (str2) : "r" (str) : "r0"); |
| |
41 return str2; |
| |
42 } |
| |
43 #define next_field(ptr) ptr = Istrend (ptr) + 1 |
| |
44 #endif |
| |
45 |
| |
46 #ifdef mips |
| |
47 #undef next_field |
| |
48 /* |
| |
49 * The compiler doesn't optimize this macro as well as it does the |
| |
50 * following function. |
| |
51 */ |
| |
52 #define next_fieldXXX(ptr) do{register unsigned c1,c2;c1= *ptr; \ |
| |
53 while((ptr++,c2= *ptr,c1)&&(ptr++,c1= *ptr,c2));}while(0) |
| |
54 static char *next_field_1 (s) char *s; { |
| |
55 /* |
| |
56 * Calling overhead is still present, but this routine is faster |
| |
57 * than strlen, and doesn't bother with some of the other math |
| |
58 * that we'd just have to undo later anyways. |
| |
59 */ |
| |
60 register unsigned c1 = *s, c2; |
| |
61 while (1) { |
| |
62 s++; c2 = *s; if (c1 == 0) break; |
| |
63 s++; c1 = *s; if (c2 == 0) break; |
| |
64 s++; c2 = *s; if (c1 == 0) break; |
| |
65 s++; c1 = *s; if (c2 == 0) break; |
| |
66 } |
| |
67 return s; |
| |
68 } |
| |
69 #define next_field(ptr) ptr=next_field_1(ptr) |
| |
70 #endif |
| |
71 |
| |
72 Code_t ZParseNotice(buffer, len, notice) |
| |
73 char *buffer; |
| |
74 int len; |
| |
75 ZNotice_t *notice; |
| |
76 { |
| |
77 char *ptr, *end; |
| |
78 unsigned long temp; |
| |
79 int maj, numfields, i; |
| |
80 |
| |
81 #ifdef __LINE__ |
| |
82 int lineno; |
| |
83 /* Note: This definition of BAD eliminates lint and compiler |
| |
84 * complains about the "while (0)", but require that the macro not |
| |
85 * be used as the "then" part of an "if" statement that also has |
| |
86 * an "else" clause. |
| |
87 */ |
| |
88 #define BAD_PACKET {lineno=__LINE__;goto badpkt;} |
| |
89 /* This one gets lint/compiler complaints. */ |
| |
90 /*#define BAD do{lineno=__LINE__;goto badpkt;}while(0)*/ |
| |
91 #else |
| |
92 #define BAD_PACKET goto badpkt |
| |
93 #endif |
| |
94 |
| |
95 (void) memset((char *)notice, 0, sizeof(ZNotice_t)); |
| |
96 |
| |
97 ptr = buffer; |
| |
98 end = buffer+len; |
| |
99 |
| |
100 notice->z_packet = buffer; |
| |
101 |
| |
102 notice->z_version = ptr; |
| |
103 if (strncmp(ptr, ZVERSIONHDR, sizeof(ZVERSIONHDR) - 1)) |
| |
104 return (ZERR_VERS); |
| |
105 ptr += sizeof(ZVERSIONHDR) - 1; |
| |
106 if (!*ptr) { |
| |
107 #ifdef Z_DEBUG |
| |
108 Z_debug ("ZParseNotice: null version string"); |
| |
109 #endif |
| |
110 return ZERR_BADPKT; |
| |
111 } |
| |
112 maj = atoi(ptr); |
| |
113 if (maj != ZVERSIONMAJOR) |
| |
114 return (ZERR_VERS); |
| |
115 next_field (ptr); |
| |
116 |
| |
117 if (ZReadAscii32(ptr, end-ptr, &temp) == ZERR_BADFIELD) |
| |
118 BAD_PACKET; |
| |
119 numfields = temp; |
| |
120 next_field (ptr); |
| |
121 |
| |
122 /*XXX 3 */ |
| |
123 numfields -= 2; /* numfields, version, and checksum */ |
| |
124 if (numfields < 0) { |
| |
125 #ifdef __LINE__ |
| |
126 lineno = __LINE__; |
| |
127 badpkt: |
| |
128 #ifdef Z_DEBUG |
| |
129 Z_debug ("ZParseNotice: bad packet from %s/%d (line %d)", |
| |
130 inet_ntoa (notice->z_uid.zuid_addr.s_addr), |
| |
131 notice->z_port, lineno); |
| |
132 #endif |
| |
133 #else |
| |
134 badpkt: |
| |
135 #ifdef Z_DEBUG |
| |
136 Z_debug ("ZParseNotice: bad packet from %s/%d", |
| |
137 inet_ntoa (notice->z_uid.zuid_addr.s_addr), |
| |
138 notice->z_port); |
| |
139 #endif |
| |
140 #endif |
| |
141 return ZERR_BADPKT; |
| |
142 } |
| |
143 |
| |
144 if (numfields) { |
| |
145 if (ZReadAscii32(ptr, end-ptr, &temp) == ZERR_BADFIELD) |
| |
146 BAD_PACKET; |
| |
147 notice->z_kind = temp; |
| |
148 numfields--; |
| |
149 next_field (ptr); |
| |
150 } |
| |
151 else |
| |
152 BAD_PACKET; |
| |
153 |
| |
154 if (numfields) { |
| |
155 if (ZReadAscii(ptr, end-ptr, (unsigned char *)¬ice->z_uid, |
| |
156 sizeof(ZUnique_Id_t)) == ZERR_BADFIELD) |
| |
157 BAD_PACKET; |
| |
158 notice->z_time.tv_sec = ntohl((u_long) notice->z_uid.tv.tv_sec); |
| |
159 notice->z_time.tv_usec = ntohl((u_long) notice->z_uid.tv.tv_usec); |
| |
160 numfields--; |
| |
161 next_field (ptr); |
| |
162 } |
| |
163 else |
| |
164 BAD_PACKET; |
| |
165 |
| |
166 if (numfields) { |
| |
167 if (ZReadAscii16(ptr, end-ptr, ¬ice->z_port) == ZERR_BADFIELD) |
| |
168 BAD_PACKET; |
| |
169 notice->z_port = htons(notice->z_port); |
| |
170 numfields--; |
| |
171 next_field (ptr); |
| |
172 } |
| |
173 else |
| |
174 BAD_PACKET; |
| |
175 |
| |
176 if (numfields) { |
| |
177 if (ZReadAscii32(ptr, end-ptr, &temp) == ZERR_BADFIELD) |
| |
178 BAD_PACKET; |
| |
179 notice->z_auth = temp; |
| |
180 numfields--; |
| |
181 next_field (ptr); |
| |
182 } |
| |
183 else |
| |
184 BAD_PACKET; |
| |
185 notice->z_checked_auth = ZAUTH_UNSET; |
| |
186 |
| |
187 if (numfields) { |
| |
188 if (ZReadAscii32(ptr, end-ptr, &temp) == ZERR_BADFIELD) |
| |
189 BAD_PACKET; |
| |
190 notice->z_authent_len = temp; |
| |
191 numfields--; |
| |
192 next_field (ptr); |
| |
193 } |
| |
194 else |
| |
195 BAD_PACKET; |
| |
196 |
| |
197 if (numfields) { |
| |
198 notice->z_ascii_authent = ptr; |
| |
199 numfields--; |
| |
200 next_field (ptr); |
| |
201 } |
| |
202 else |
| |
203 BAD_PACKET; |
| |
204 |
| |
205 if (numfields) { |
| |
206 notice->z_class = ptr; |
| |
207 numfields--; |
| |
208 next_field (ptr); |
| |
209 } |
| |
210 else |
| |
211 notice->z_class = ""; |
| |
212 |
| |
213 if (numfields) { |
| |
214 notice->z_class_inst = ptr; |
| |
215 numfields--; |
| |
216 next_field (ptr); |
| |
217 } |
| |
218 else |
| |
219 notice->z_class_inst = ""; |
| |
220 |
| |
221 if (numfields) { |
| |
222 notice->z_opcode = ptr; |
| |
223 numfields--; |
| |
224 next_field (ptr); |
| |
225 } |
| |
226 else |
| |
227 notice->z_opcode = ""; |
| |
228 |
| |
229 if (numfields) { |
| |
230 notice->z_sender = ptr; |
| |
231 numfields--; |
| |
232 next_field (ptr); |
| |
233 } |
| |
234 else |
| |
235 notice->z_sender = ""; |
| |
236 |
| |
237 if (numfields) { |
| |
238 notice->z_recipient = ptr; |
| |
239 numfields--; |
| |
240 next_field (ptr); |
| |
241 } |
| |
242 else |
| |
243 notice->z_recipient = ""; |
| |
244 |
| |
245 if (numfields) { |
| |
246 notice->z_default_format = ptr; |
| |
247 numfields--; |
| |
248 next_field (ptr); |
| |
249 } |
| |
250 else |
| |
251 notice->z_default_format = ""; |
| |
252 |
| |
253 /*XXX*/ |
| |
254 if (ZReadAscii32(ptr, end-ptr, &temp) == ZERR_BADFIELD) |
| |
255 BAD_PACKET; |
| |
256 notice->z_checksum = temp; |
| |
257 numfields--; |
| |
258 next_field (ptr); |
| |
259 |
| |
260 if (numfields) { |
| |
261 notice->z_multinotice = ptr; |
| |
262 numfields--; |
| |
263 next_field (ptr); |
| |
264 } |
| |
265 else |
| |
266 notice->z_multinotice = ""; |
| |
267 |
| |
268 if (numfields) { |
| |
269 if (ZReadAscii(ptr, end-ptr, (unsigned char *)¬ice->z_multiuid, |
| |
270 sizeof(ZUnique_Id_t)) == ZERR_BADFIELD) |
| |
271 BAD_PACKET; |
| |
272 notice->z_time.tv_sec = ntohl((u_long) notice->z_multiuid.tv.tv_sec); |
| |
273 notice->z_time.tv_usec = ntohl((u_long) notice->z_multiuid.tv.tv_usec); |
| |
274 numfields--; |
| |
275 next_field (ptr); |
| |
276 } |
| |
277 else |
| |
278 notice->z_multiuid = notice->z_uid; |
| |
279 |
| |
280 for (i=0;i<Z_MAXOTHERFIELDS && numfields;i++,numfields--) { |
| |
281 notice->z_other_fields[i] = ptr; |
| |
282 next_field (ptr); |
| |
283 } |
| |
284 notice->z_num_other_fields = i; |
| |
285 |
| |
286 for (i=0;i<numfields;i++) |
| |
287 next_field (ptr); |
| |
288 |
| |
289 notice->z_message = (caddr_t) ptr; |
| |
290 notice->z_message_len = len-(ptr-buffer); |
| |
291 |
| |
292 return (ZERR_NONE); |
| |
293 } |