1 /**********************************************************
2 * File: qipc_common.c
3 * Created at Mon May 7 23:07:41 2001 by lev // lev@serebryakov.spb.ru
4 *
5 * $Id: qipc_common.c,v 1.6 2001/09/17 18:56:48 lev Exp $
6 **********************************************************/
7 #include "headers.h"
8 #include <stdarg.h>
9 #include "byteop.h"
10
11 /* Allocate and receive IPC packet via UDP -- should be freed with xfree() */
receive_ipc_packet_udp(int s,struct sockaddr_in * sa)12 evtany_t *receive_ipc_packet_udp(int s, struct sockaddr_in *sa)
13 {
14 BYTE bf[4];
15 UINT32 l;
16 evtany_t *pkt;
17
18 if(recvfrom(s,bf,4,MSG_PEEK,sa,sizeof(*sa))!=4) return NULL;
19 l = FETCH32(bf);
20 if(!(pkt = xmalloc(l))) return NULL;
21 if(recvfrom(s,pkt,l,MSG_WAITALL,sa,sizeof(*sa))!=l) {
22 xfree(pkt);
23 return NULL;
24 }
25 pkt->fulllength = l;
26 return pkt;
27 }
28
29 /* Allocate and receive IPC packet via TCP -- should be freed with xfree() */
receive_ipc_packet_tcp(int s)30 evtany_t *receive_ipc_packet_tcp(int s)
31 {
32 BYTE bf[4];
33 UINT32 l;
34 evtany_t *pkt;
35
36 if(recv(s,bf,4,MSG_PEEK)!=4) return NULL;
37 l = FETCH32(bf);
38 if(!(pkt = xmalloc(l))) return NULL;
39 if(recv(s,pkt,l,MSG_WAITALL)!=l) {
40 xfree(pkt);
41 return NULL;
42 }
43 pkt->fulllength = l;
44 return pkt;
45 }
46
47 /* Decode packet by signature */
unpack_ipc_packet(CHAR * data,int * len,char * sig,...)48 int unpack_ipc_packet(CHAR *data, int *len, char *sig, ...)
49 {
50 va_list args;
51 DWORD *pl;
52 CHAR *pc;
53 CHAR *ps;
54 CHAR **pps;
55 ftnaddr_t *pa;
56 ninfo_t *pn;
57 slist_t **ppsl, *psl;
58 faslist_t **ppasl, *pasl;
59 falist_t **ppal, *pal;
60 long l,i,N;
61 int rc = 0;
62
63 va_start(args, sig);
64
65 while(*sig) {
66 switch(*sig) {
67 case 's': /* Strings, allocate here */
68 if(*len<4) { va_end(args); return rc; }
69 l=FETCH32(data); INC32(data); *len-=4;
70 pps=va_arg(args,CHAR **);
71 if(l) {
72 if(*len<l || data[l-1]) { va_end(args); return rc; }
73 *pps=xmalloc(l);
74 memcpy(*pps,data,l); *len-=l; data+=l;
75 } else {
76 *pps=NULL;
77 }
78 rc++;
79 break;
80 case 'd': /* 32 bit unsigned integer */
81 if(*len<4) { va_end(args); return rc; }
82 pl=va_arg(args, DWORD *);
83 *pl=FETCH32(data); INC32(data); *len-=4;
84 rc++;
85 break;
86 case 'c': /* One character */
87 if(!*len) { va_end(args); return rc; }
88 pc=va_arg(args,CHAR *);
89 *pc=*data; data++; *len--;
90 rc++;
91 break;
92 case 'a': /* 4D FTN address */
93 if(*len<2*4) { va_end(args); return rc; }
94 pa=va_arg(args,ftnaddr_t *);
95 pa->z=FETCH16(data); INC16(data); *len-=2;
96 pa->n=FETCH16(data); INC16(data); *len-=2;
97 pa->f=FETCH16(data); INC16(data); *len-=2;
98 pa->p=FETCH16(data); INC16(data); *len-=2;
99 rc++;
100 break;
101 case 'l': /* List of strings or addresses */
102 if(*len<2) { va_end(args); return rc; }
103 N=FETCH16(data); INC16(data); *len-=2;
104 sig++;
105 switch(*sig) {
106 case 's': /* List of strings (slist_t) */
107 if(*len<4*N) { va_end(args); return rc; }
108 ppsl=va_arg(args,slist_t **);
109 psl=*ppsl=NULL;
110 for(i=0;i<N;i++) {
111 if(!psl) psl=*ppsl=xcalloc(1,sizeof(*psl));
112 else { psl->next=xcalloc(1,sizeof(*psl)); psl=psl->next; }
113 l=*len;
114 if(1!=unpack_ipc_packet(data,len,"s",&psl->str)) { va_end(args); return rc; }
115 data+=(l-*len);
116 }
117 break;
118 case 'a': /* List of addresses (falist_t) */
119 if(*len<8*N) { va_end(args); return rc; }
120 ppal=va_arg(args,falist_t **);
121 pal=*ppal=NULL;
122 for(i=0;i<N;i++) {
123 if(!pal) pal=*ppal=xcalloc(1,sizeof(*pal));
124 else { pal->next=xcalloc(1,sizeof(*pal)); pal=pal->next; }
125 if(1!=unpack_ipc_packet(data,len,"a",&pal->addr)) { va_end(args); return rc; }
126 data+=8;
127 }
128 break;
129 default:
130 va_end(args);
131 return rc;
132 }
133 rc++;
134 break;
135 case 'n': /* Node info "lassssdsds" */
136 pn=va_arg(args,ninfo_t *);
137 l=*len;
138 if(9!=unpack_ipc_packet(data,len,"lassssdsds",
139 &pn->addrs,
140 &pn->name,
141 &pn->place,
142 &pn->sysop,
143 &pn->phone,
144 &pn->speed,
145 &pn->flags,
146 &pn->time,
147 &pn->wtime)) { va_end(args); return rc; }
148 data+=(l-*len);
149 break;
150 default:
151 va_end(args);
152 return rc;
153 }
154 sig++;
155 }
156 va_end(args);
157 return rc;
158 }
159
160 /* Encode packet by signature */
pack_ipc_packet(CHAR * data,int maxlen,int * len,char * sig,...)161 int pack_ipc_packet(CHAR *data, int maxlen, int *len, char *sig, ...)
162 {
163 va_list args;
164 DWORD pl;
165 CHAR pc;
166 CHAR *ps;
167 ftnaddr_t *pa;
168 long l;
169 int slen = maxlen;
170 int rc = 0;
171
172 *len=0;
173 va_start(args, sig);
174 while(*sig) {
175 switch(*sig) {
176 case 's': /* String */
177 if(maxlen<4) { va_end(args); return rc; }
178 ps=va_arg(args,CHAR *);
179 if(ps) l=strlen(ps)+1;
180 else l=0;
181 STORE32(data,l); INC32(data); maxlen-=4;
182 if(l) {
183 if(maxlen<l) { va_end(args); return rc; }
184 memcpy(data,ps,l); data+=l; maxlen-=l;
185 }
186 rc++;
187 break;
188 case 'd': /* 32bit unsigned integer */
189 if(maxlen<4) { va_end(args); return rc; }
190 pl=va_arg(args, DWORD);
191 STORE32(data,pl); INC32(data); maxlen-=4;
192 rc++;
193 break;
194 case 'c': /* One character */
195 if(!maxlen) { va_end(args); return rc; }
196 pc=va_arg(args,CHAR);
197 *data=pc; data++; maxlen--;
198 rc++;
199 break;
200 case 'a': /* 4D FTN address */
201 if(maxlen<8) { va_end(args); return rc; }
202 pa=va_arg(args,ftnaddr_t);
203 STORE16(data,pa->z); INC32(data); maxlen-=2;
204 STORE16(data,pa->n); INC32(data); maxlen-=2;
205 STORE16(data,pa->f); INC32(data); maxlen-=2;
206 STORE16(data,pa->p); INC32(data); maxlen-=2;
207 rc++;
208 break;
209 case 'l': /* List of strings or addresses */
210 if(maxlen<2) { va_end(args); return rc; }
211 *ps=data;
212 N=0;
213 STORE16(data,N); INC16(data); *len-=2;
214 sig++;
215 switch(*sig) {
216 case 's': /* List of strings (slist_t) */
217 if(maxlen<4*N) { va_end(args); return rc; }
218 psl=va_arg(args,slist_t *);
219 if(psl) do {
220 N++;
221 if(1!=pack_ipc_packet(data,len,&l,"s",psl->str)) { va_end(args); return rc; }
222 data+=l;
223 } while(psl=psl->next);
224 break;
225 case 'a': /* List of addresses (falist_t) */
226 if(maxlen<4*N) { va_end(args); return rc; }
227 pal=va_arg(args,falist_t *);
228 if(pal) do {
229 N++;
230 if(1!=pack_ipc_packet(data,len,&l,"a",&pal->addr)) { va_end(args); return rc; }
231 data+=l;
232 } while(pal=pal->next);
233 break;
234 default:
235 va_end(args);
236 return rc;
237 }
238 STORE16(ps,(N&0x0000ffff)); /* Store real number of elements back */
239 rc++;
240 break;
241 case 'n': /* Node info */
242 pn=va_arg(args,ninfo_t *);
243 if(9!=pack_ipc_packet(data,len,&l,"lassssdsds",
244 pn->addrs,
245 pn->name,
246 pn->place,
247 pn->sysop,
248 pn->phone,
249 pn->speed,
250 pn->flags,
251 pn->time,
252 pn->wtime)) { va_end(args); return rc; }
253 data+=l;
254 break;
255 default:
256 va_end(args);
257 return rc;
258 }
259 sig++;
260 }
261 va_end(args);
262 *len=slen-maxlen;
263 return rc;
264 }
265
266 /* Encode packet with DES (pkt should be bigger than length!) */
encode_ipc_packet(evtany_t * pkt,sessenccontext_t * cx)267 void encode_ipc_packet(evtany_t *pkt, sessenccontext_t *cx)
268 {
269 int len8 = ((pkg->fulllength>>3)|(pkg->fulllength&0x07?1:0))<<3;
270 int i;
271 for(i=pkg->fulllength;i<len8;i++) pkt->data[i] = 0;
272 pkg->fulllength = len8;
273 des_cbc_encrypt(cx->cx,cx->iv,pkg->data,pkg->data,len8);
274 }
275
276 /* Decode packet with DES (pkt should be bigger than length!) */
decode_ipc_packet(evtany_t * pkt,sessenccontext_t * cx)277 void decode_ipc_packet(evtany_t *pkt, sessenccontext_t *cx)
278 {
279 int len8 = ((pkg->fulllength>>3)|(pkg->fulllength&0x07?1:0))<<3;
280 int i;
281 for(i=pkg->fulllength;i<len8;i++) pkt->data[i] = 0;
282 pkg->fulllength = len8;
283 des_cbc_decrypt(cx->cx,cx->iv,pkg->data,pkg->data,len8);
284 }
285