]> asedeno.scripts.mit.edu Git - 1ts-debian.git/blob - zephyr/lib/ZParseNot.c
new upstream version
[1ts-debian.git] / zephyr / lib / ZParseNot.c
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  *      $Id: ZParseNot.c 2344 2009-03-24 03:40:55Z kcr $
7  *
8  *      Copyright (c) 1987,1991 by the Massachusetts Institute of Technology.
9  *      For copying and distribution information, see the file
10  *      "mit-copyright.h". 
11  */
12
13 #ifndef lint
14 static const char rcsid_ZParseNotice_c[] =
15     "$Zephyr: /mit/zephyr/src/lib/RCS/ZParseNotice.c,v 1.22 91/03/29 03:34:46 raeburn Exp $";
16 #endif
17
18 #include <internal.h>
19
20 /* Skip to the next NUL-terminated field in the packet. */
21 static char *
22 next_field(char *ptr,
23            char *end)
24 {
25     while (ptr < end && *ptr != '\0')
26         ptr++;
27     if (ptr < end)
28         ptr++;
29     return (ptr);
30 }
31
32 Code_t
33 ZParseNotice(char *buffer,
34              int len,
35              ZNotice_t *notice)
36 {
37     char *ptr, *end;
38     unsigned long temp;
39     int maj, numfields, i;
40
41 #ifdef __LINE__
42     int lineno;
43     /* Note: This definition of BAD eliminates lint and compiler
44      * complains about the "while (0)", but require that the macro not
45      * be used as the "then" part of an "if" statement that also has
46      * an "else" clause.
47      */
48 #define BAD_PACKET      {lineno=__LINE__;goto badpkt;}
49     /* This one gets lint/compiler complaints.  */
50 /*#define BAD   do{lineno=__LINE__;goto badpkt;}while(0)*/
51 #else
52 #define BAD_PACKET      goto badpkt
53 #endif
54
55     (void) memset((char *)notice, 0, sizeof(ZNotice_t));
56         
57     ptr = buffer;
58     end = buffer+len;
59
60     notice->z_packet = buffer;
61     
62     notice->z_version = ptr;
63     if (strncmp(ptr, ZVERSIONHDR, sizeof(ZVERSIONHDR) - 1))
64         return (ZERR_VERS);
65     ptr += sizeof(ZVERSIONHDR) - 1;
66     if (!*ptr) {
67 #ifdef Z_DEBUG
68         Z_debug ("ZParseNotice: null version string");
69 #endif
70         return ZERR_BADPKT;
71     }
72     maj = atoi(ptr);
73     if (maj != ZVERSIONMAJOR)
74         return (ZERR_VERS);
75     ptr = next_field(ptr, end);
76
77     if (ZReadAscii32(ptr, end-ptr, &temp) == ZERR_BADFIELD)
78         BAD_PACKET;
79     numfields = temp;
80     notice->z_num_hdr_fields = numfields;
81     ptr = next_field(ptr, end);
82
83     /*XXX 3 */
84     numfields -= 2; /* numfields, version, and checksum */
85     if (numfields < 0) {
86 #ifdef __LINE__
87         lineno = __LINE__;
88       badpkt:
89 #ifdef Z_DEBUG
90         Z_debug ("ZParseNotice: bad packet from %s/%d (line %d)",
91                  inet_ntoa (notice->z_uid.zuid_addr.s_addr),
92                  notice->z_port, lineno);
93 #endif
94 #else
95     badpkt:
96 #ifdef Z_DEBUG
97         Z_debug ("ZParseNotice: bad packet from %s/%d",
98                  inet_ntoa (notice->z_uid.zuid_addr.s_addr),
99                  notice->z_port);
100 #endif
101 #endif
102         return ZERR_BADPKT;
103     }
104
105     if (numfields && ptr < end) {
106         if (ZReadAscii32(ptr, end-ptr, &temp) == ZERR_BADFIELD)
107             BAD_PACKET;
108         notice->z_kind = (ZNotice_Kind_t)temp;
109         numfields--;
110         ptr = next_field(ptr, end);
111     }
112     else
113         BAD_PACKET;
114         
115     if (numfields && ptr < end) {
116         if (ZReadAscii(ptr, end-ptr, (unsigned char *)&notice->z_uid,
117                        sizeof(ZUnique_Id_t)) == ZERR_BADFIELD)
118             BAD_PACKET;
119         notice->z_time.tv_sec = ntohl((u_long) notice->z_uid.tv.tv_sec);
120         notice->z_time.tv_usec = ntohl((u_long) notice->z_uid.tv.tv_usec);
121         numfields--;
122         ptr = next_field(ptr, end);
123     }
124     else
125         BAD_PACKET;
126         
127     if (numfields && ptr < end) {
128         if (ZReadAscii16(ptr, end-ptr, &notice->z_port) == ZERR_BADFIELD)
129             BAD_PACKET;
130         notice->z_port = htons(notice->z_port);
131         numfields--;
132         ptr = next_field(ptr, end);
133     }
134     else
135         BAD_PACKET;
136
137     if (numfields && ptr < end) {
138         if (ZReadAscii32(ptr, end-ptr, &temp) == ZERR_BADFIELD)
139             BAD_PACKET;
140         notice->z_auth = temp;
141         numfields--;
142         ptr = next_field(ptr, end);
143     }
144     else
145         BAD_PACKET;
146     notice->z_checked_auth = ZAUTH_UNSET;
147         
148     if (numfields && ptr < end) {
149         if (ZReadAscii32(ptr, end-ptr, &temp) == ZERR_BADFIELD)
150             BAD_PACKET;
151         notice->z_authent_len = temp;
152         numfields--;
153         ptr = next_field(ptr, end);
154     }
155     else
156         BAD_PACKET;
157
158     if (numfields && ptr < end) {
159         notice->z_ascii_authent = ptr;
160         numfields--;
161         ptr = next_field(ptr, end);
162     }
163     else
164         BAD_PACKET;
165
166     if (numfields && ptr < end) {
167         notice->z_class = ptr;
168         numfields--;
169         ptr = next_field(ptr, end);
170     }
171     else
172         notice->z_class = "";
173         
174     if (numfields && ptr < end) {
175         notice->z_class_inst = ptr;
176         numfields--;
177         ptr = next_field(ptr, end);
178     }
179     else
180         notice->z_class_inst = "";
181
182     if (numfields && ptr < end) {
183         notice->z_opcode = ptr;
184         numfields--;
185         ptr = next_field(ptr, end);
186     }
187     else
188         notice->z_opcode = "";
189
190     if (numfields && ptr < end) {
191         notice->z_sender = ptr;
192         numfields--;
193         ptr = next_field(ptr, end);
194     }
195     else
196         notice->z_sender = "";
197
198     if (numfields && ptr < end) {
199         notice->z_recipient = ptr;
200         numfields--;
201         ptr = next_field(ptr, end);
202     }
203     else
204         notice->z_recipient = "";
205
206     if (numfields && ptr < end) {
207         notice->z_default_format = ptr;
208         numfields--;
209         ptr = next_field(ptr, end);
210     }
211     else
212         notice->z_default_format = "";
213         
214     if (numfields && ptr < end) {
215       notice->z_ascii_checksum = ptr;
216
217       if (ZReadAscii32(ptr, end-ptr, &temp) == ZERR_BADFIELD)
218         notice->z_checksum = 0;
219       else
220         notice->z_checksum = temp;
221
222       numfields--;
223       ptr = next_field (ptr, end);
224     }
225     else 
226       {
227         notice->z_ascii_checksum = "";
228         notice->z_checksum = 0;
229       }
230
231     if (numfields && ptr < end) {
232         notice->z_multinotice = ptr;
233         numfields--;
234         ptr = next_field(ptr, end);
235     }
236     else
237         notice->z_multinotice = "";
238
239     if (numfields && ptr < end) {
240         if (ZReadAscii(ptr, end-ptr, (unsigned char *)&notice->z_multiuid,
241                        sizeof(ZUnique_Id_t)) == ZERR_BADFIELD)
242             BAD_PACKET;
243         notice->z_time.tv_sec = ntohl((u_long) notice->z_multiuid.tv.tv_sec);
244         notice->z_time.tv_usec = ntohl((u_long) notice->z_multiuid.tv.tv_usec);
245         numfields--;
246         ptr = next_field(ptr, end);
247     }
248     else
249         notice->z_multiuid = notice->z_uid;
250
251     if (numfields && ptr < end) {
252         /* we will take it on faith that ipv6 addresses are longer than ipv4
253            addresses */
254         unsigned char addrbuf[sizeof(notice->z_sender_sockaddr.ip6.sin6_addr)];
255         int len;
256
257         /* because we're paranoid about naughtily misformated packets */
258         if (memchr(ptr, '\0', end - ptr) == NULL)
259             BAD_PACKET;
260
261         if (*ptr == 'Z') {
262             if (ZReadZcode((unsigned char *)ptr, addrbuf,
263                            sizeof(addrbuf), &len) == ZERR_BADFIELD)
264                 BAD_PACKET;
265         } else {
266             len = sizeof(notice->z_sender_sockaddr.ip4.sin_addr);
267             if (ZReadAscii(ptr, end - ptr, (unsigned char *)addrbuf,
268                            len) == ZERR_BADFIELD)
269                 BAD_PACKET;
270         }
271
272         if (len == sizeof(notice->z_sender_sockaddr.ip6.sin6_addr)) {
273             notice->z_sender_sockaddr.ip6.sin6_family = AF_INET6;
274             memcpy(&notice->z_sender_sockaddr.ip6.sin6_addr, addrbuf, len);
275         } else if (len == sizeof(notice->z_sender_sockaddr.ip4.sin_addr)) {
276             notice->z_sender_sockaddr.ip4.sin_family = AF_INET;
277             memcpy(&notice->z_sender_sockaddr.ip4.sin_addr, addrbuf, len);
278         } else
279             BAD_PACKET;
280
281         numfields--;
282         ptr = next_field(ptr, end);
283     } else {
284         memset(&notice->z_sender_sockaddr, 0,
285                sizeof notice->z_sender_sockaddr);
286         notice->z_sender_sockaddr.ip4.sin_family = AF_INET;
287         notice->z_sender_sockaddr.ip4.sin_addr = notice->z_uid.zuid_addr;
288     }
289
290     if (numfields && ptr < end) {
291         if (ZReadAscii16(ptr, end-ptr, &notice->z_charset) == ZERR_BADFIELD)
292             BAD_PACKET;
293         notice->z_charset = htons(notice->z_charset);
294
295         numfields--;
296         ptr = next_field(ptr, end);
297     } else
298         notice->z_charset = ZCHARSET_UNKNOWN;
299     
300     for (i=0;ptr < end && i<Z_MAXOTHERFIELDS && numfields;i++,numfields--) {
301         notice->z_other_fields[i] = ptr;
302         ptr = next_field(ptr, end);
303     }
304     notice->z_num_other_fields = i;
305     
306     for (i=0;ptr < end && numfields;numfields--)
307         ptr = next_field(ptr, end);
308
309     if (numfields || *(ptr - 1) != '\0')
310         BAD_PACKET;
311
312     notice->z_message = (caddr_t) ptr;
313     notice->z_message_len = len-(ptr-buffer);
314
315     return (ZERR_NONE);
316 }