1/* 2** BPALogin - lightweight portable BIDS2 login client 3** Copyright (c) 2001-3 Shane Hyde, and others. 4** 5** This program is free software; you can redistribute it and/or modify 6** it under the terms of the GNU General Public License as published by 7** the Free Software Foundation; either version 2 of the License, or 8** (at your option) any later version. 9** 10** This program is distributed in the hope that it will be useful, 11** but WITHOUT ANY WARRANTY; without even the implied warranty of 12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13** GNU General Public License for more details. 14** 15** You should have received a copy of the GNU General Public License 16** along with this program; if not, write to the Free Software 17** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18** 19*/ 20 21#include "bpalogin.h" 22 23void add_trans_data(struct transaction * t,char *p,int count) 24{ 25 memcpy(t->data+t->length,p,count); 26 t->length += count; 27} 28 29void add_int2field(struct transaction * t,INT2 v) 30{ 31 add_trans_data(t,(char *)&v,2); 32} 33 34void add_int4field(struct transaction * t,INT4 v) 35{ 36 add_trans_data(t,(char *)&v,4); 37} 38 39void add_string(struct transaction * t,char *s) 40{ 41 add_int2field(t,htons((INT2)(strlen(s)+4))); 42 add_trans_data(t,s,strlen(s)); 43} 44 45void add_data(struct transaction * t,char *s,int c) 46{ 47 add_int2field(t,htons((INT2)(c+4))); 48 add_trans_data(t,s,c); 49} 50 51void add_field_string(struct session *s,struct transaction * t,INT2 fn,char * p) 52{ 53 s->debug(2,"Sending parm %d value %s\n",fn,p); 54 55 add_int2field(t,htons(fn)); 56 add_string(t,p); 57} 58 59void add_field_data(struct session *s,struct transaction * t,INT2 fn,char * p,int c) 60{ 61 s->debug(2,"Sending parm %d value %s\n",fn,p); 62 63 add_int2field(t,htons(fn)); 64 add_data(t,p,c); 65} 66 67void add_field_INT2(struct session *s,struct transaction * t,INT2 fn,INT2 v) 68{ 69 s->debug(2,"Sending parm %d value %d\n",fn,v); 70 71 add_int2field(t,htons(fn)); 72 add_int2field(t,htons(6)); 73 add_int2field(t,htons(v)); 74} 75 76void add_field_INT4(struct session *s,struct transaction * t,INT2 fn,INT4 v) 77{ 78 s->debug(2,"Sending parm %d value %d\n",fn,v); 79 80 add_int2field(t,htons(fn)); 81 add_int2field(t,htons(8)); 82 add_int4field(t,htonl(v)); 83} 84 85void start_transaction(struct transaction * t,INT2 msgtype,INT4 sessionid) 86{ 87 t->length = 0; 88 memset(t->data,0,1512); 89 add_int2field(t,htons(msgtype)); 90 add_int2field(t,htons(0)); 91 add_int4field(t,htonl(sessionid)); 92} 93 94void dump_transaction(struct session * s,struct transaction * t) 95{ 96 int i; 97 char * p = t->data; 98 i = 0; 99 while(i < t->length) 100 { 101 s->debug(3,"%d:%02x ",i,(unsigned char)*(p)); 102 103 p++; 104 i++; 105 } 106 s->debug(3,"\n"); 107 108} 109 110void dump_sent_transaction(struct session *s,struct transaction * t) 111{ 112 s->debug(3,"Sent transaction:\n"); 113 dump_transaction(s,t); 114} 115 116void dump_recv_transaction(struct session *s,struct transaction * t) 117{ 118 s->debug(3,"Received transaction:\n"); 119 dump_transaction(s,t); 120} 121 122void send_transaction(struct session *s,int socket,struct transaction * t) 123{ 124 int r; 125 INT2 * lll; 126 127 lll = (INT2 *)(t->data+2); 128 *lll = htons((INT2)t->length); 129 130 r = send(socket,(void *)t,t->length,0); 131 dump_sent_transaction(s,t); 132} 133 134void send_udp_transaction(struct session * s,struct transaction * t) 135{ 136 int r; 137 138 INT2 * lll; 139 140 lll = (INT2 *)(t->data+2); 141 *lll = htons((INT2)t->length); 142 143 s->fromaddr.sin_port = htons(s->statusport); 144 r = sendto(s->listensock,(void *)t,t->length,0,(struct sockaddr *)&s->fromaddr,sizeof(s->fromaddr)); 145 dump_sent_transaction(s,t); 146} 147 148INT2 receive_transaction(struct session *s,int socket,struct transaction * t) 149{ 150 INT2 * v; 151 int r = recv(socket,(char *)t,1500,0); 152 153 t->length = r; 154 dump_recv_transaction(s,t); 155 156 v = (INT2 *)t; 157 158 return r>0?ntohs(*v):0; 159} 160 161int check_hb_packet(struct session * s,struct transaction * t,int length) 162{ 163 INT2 type; 164 165 type = ntohs(*(INT2 *)t); 166 if(type != T_MSG_STATUS_REQ) 167 { 168 s->debug(0,"Incorrect transaction type %d",type); 169 return 0; 170 } 171 172 if(length != 8) 173 { 174 s->debug(0,"Incorrect transaction length %d",length); 175 return 0; 176 } 177 return 1; 178} 179 180INT2 receive_udp_transaction(struct session *s,int socket,struct transaction * t,struct sockaddr_in *addr) 181{ 182 struct timeval timeval; 183 fd_set readfds; 184 INT2 * v; 185 int l = sizeof(struct sockaddr_in); 186 int r,i; 187 188 timeval.tv_sec = s->maxheartbeat; 189 timeval.tv_usec = 0; 190 FD_ZERO(&readfds); 191 FD_SET(socket,&readfds); 192 193 r = select(socket+1,&readfds,NULL,NULL,&timeval); 194 195 if(r == -1) 196 { 197 return (INT2) 0xfffe; 198 } 199 else if(!r) 200 { 201 return (INT2) 0xffff; 202 } 203 else 204 { 205 r = recvfrom(socket,(char *)t,1500,0,(struct sockaddr*)addr,&l); 206 if(r==-1) 207 return (INT2) 0xfffe; 208 209 if(s->lastheartbeat + s->minheartbeat > time(NULL)) 210 { 211 s->recenthb++; 212 if(s->recenthb > 3) 213 { 214 s->debug(0,"Heartbeats arriving too quickly - discarding\n"); 215 return (INT2)0xfffd; 216 217 } 218 } 219 else 220 s->recenthb = 0; 221 222 s->lastheartbeat = time(NULL); 223 } 224 225 for(i = 0;i<s->tsmcount;i++) 226 { 227 if(addr->sin_addr.s_addr == s->tsmlist_in[i].sin_addr.s_addr) 228 break; 229 } 230 if(i == s->tsmcount) 231 { 232 s->debug(0,"Received a heartbeat from unexpected source %s:%d\n",inet_ntoa(addr->sin_addr),ntohs(addr->sin_port)); 233 return (INT2)0xfffd; 234 } 235 236 t->length = r; 237 238 dump_recv_transaction(s,t); 239 /* 240 ** Lets make sure this packet is structured correctly 241 */ 242 if(!check_hb_packet(s,t,r)) 243 { 244 return (INT2)0xfffd; 245 } 246 247 dump_recv_transaction(s,t); 248 249 v = (INT2 *)t; 250 251 return r>0?ntohs(*v):0; 252} 253 254char * locate_parm(struct transaction * t,INT2 parm) 255{ 256 char * p = t->data,*pp,*lp,*vp; 257 INT2 p1; 258 INT2 l; 259 int i; 260 261 i = 8; 262 p += 8; 263 while(i < t->length) 264 { 265 pp = p; 266 lp = p+2; 267 vp = p+4; 268 269 l = read_INT2(lp); 270 p1 = read_INT2(pp); 271 272 if(parm == p1) 273 { 274 return vp; 275 } 276 p += l; 277 i += l; 278 } 279 return NULL; 280} 281 282int extract_valueINT2(struct session *s,struct transaction * t,INT2 parm,INT2 *v) 283{ 284 INT2 * pp = (INT2 *)locate_parm(t,parm); 285 if(pp) 286 { 287 *v = read_INT2(pp); 288 s->debug(2,"Received parm %d value %d\n",parm,*v); 289 290 return TRUE; 291 } 292 return FALSE; 293} 294 295int extract_valueINT4(struct session *s,struct transaction * t,INT2 parm,INT4 *v) 296{ 297 INT4 * pp = (INT4 *)locate_parm(t,parm); 298 if(pp) 299 { 300 *v = read_INT4(pp); 301 s->debug(2,"Received parm %d value %d\n",parm,*v); 302 303 return TRUE; 304 } 305 return FALSE; 306} 307 308int extract_valuestring(struct session *s,struct transaction * t,INT2 parm,char * v) 309{ 310 char * pp = locate_parm(t,parm); 311 if(pp) 312 { 313 INT2 l = read_INT2(pp-2); 314 memcpy(v,pp,l-4); 315 *(v+l-4) = 0; 316 s->debug(2,"Received parm %d value %s\n",parm,v); 317 318 return TRUE; 319 } 320 return FALSE; 321} 322 323INT2 read_INT2(void *pp) 324{ 325#ifdef __i386 326 return ntohs(*((INT2*)pp)); 327#else 328 unsigned char * p = (unsigned char *)pp; 329 return (((INT2)(*p))<<8) + ((INT2)(*(p+1))); 330#endif 331} 332 333INT4 read_INT4(void *pp) 334{ 335#ifdef __i386 336 return ntohl(*((INT4*)pp)); 337#else 338 unsigned char * p = (unsigned char *)pp; 339 return (((INT4)(*p))<<24) + (((INT4)(*(p+1)))<<16) + (((INT4)(*(p+2)))<<8) + (((INT4)(*(p+3)))); 340#endif 341} 342