00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <string.h>
00025
00026 #include <mISDNuser/mISDNlib.h>
00027 #include <mISDNuser/isdn_net.h>
00028 #include <mISDNuser/l3dss1.h>
00029 #include <mISDNuser/net_l3.h>
00030
00031
00032
00033 #define MISDN_IE_DEBG 0
00034
00035
00036 static void strnncpy(char *dest, char *src, int len, int dst_len)
00037 {
00038 if (len > dst_len-1)
00039 len = dst_len-1;
00040 strncpy((char *)dest, (char *)src, len);
00041 dest[len] = '\0';
00042 }
00043
00044
00045
00046 static void enc_ie_complete(unsigned char **ntmode, msg_t *msg, int complete, int nt, struct misdn_bchannel *bc)
00047 {
00048 unsigned char *p;
00049 Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
00050
00051 if (complete<0 || complete>1)
00052 {
00053 printf("%s: ERROR: complete(%d) is out of range.\n", __FUNCTION__, complete);
00054 return;
00055 }
00056
00057 if (complete)
00058 if (MISDN_IE_DEBG) printf(" complete=%d\n", complete);
00059
00060 if (complete)
00061 {
00062 p = msg_put(msg, 1);
00063 if (nt)
00064 {
00065 *ntmode = p;
00066 } else
00067 qi->QI_ELEMENT(sending_complete) = p - (unsigned char *)qi - sizeof(Q931_info_t);
00068
00069 p[0] = IE_COMPLETE;
00070 }
00071 }
00072
00073 static void dec_ie_complete(unsigned char *p, Q931_info_t *qi, int *complete, int nt, struct misdn_bchannel *bc)
00074 {
00075 *complete = 0;
00076 if (!nt)
00077 {
00078 if (qi->QI_ELEMENT(sending_complete))
00079 *complete = 1;
00080 } else
00081 if (p)
00082 *complete = 1;
00083
00084 if (*complete)
00085 if (MISDN_IE_DEBG) printf(" complete=%d\n", *complete);
00086 }
00087
00088
00089
00090 static void enc_ie_bearer(unsigned char **ntmode, msg_t *msg, int coding, int capability, int mode, int rate, int multi, int user, int nt, struct misdn_bchannel *bc)
00091 {
00092 unsigned char *p;
00093 Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
00094 int l;
00095
00096 if (coding<0 || coding>3)
00097 {
00098 printf("%s: ERROR: coding(%d) is out of range.\n", __FUNCTION__, coding);
00099 return;
00100 }
00101 if (capability<0 || capability>31)
00102 {
00103 printf("%s: ERROR: capability(%d) is out of range.\n", __FUNCTION__, capability);
00104 return;
00105 }
00106 if (mode<0 || mode>3)
00107 {
00108 printf("%s: ERROR: mode(%d) is out of range.\n", __FUNCTION__, mode);
00109 return;
00110 }
00111 if (rate<0 || rate>31)
00112 {
00113 printf("%s: ERROR: rate(%d) is out of range.\n", __FUNCTION__, rate);
00114 return;
00115 }
00116 if (multi>127)
00117 {
00118 printf("%s: ERROR: multi(%d) is out of range.\n", __FUNCTION__, multi);
00119 return;
00120 }
00121 if (user>31)
00122 {
00123 printf("%s: ERROR: user L1(%d) is out of range.\n", __FUNCTION__, rate);
00124 return;
00125 }
00126 if (rate!=24 && multi>=0)
00127 {
00128 printf("%s: WARNING: multi(%d) is only possible if rate(%d) would be 24.\n", __FUNCTION__, multi, rate);
00129 multi = -1;
00130 }
00131
00132 if (MISDN_IE_DEBG) printf(" coding=%d capability=%d mode=%d rate=%d multi=%d user=%d\n", coding, capability, mode, rate, multi, user);
00133
00134 l = 2 + (multi>=0) + (user>=0);
00135 p = msg_put(msg, l+2);
00136 if (nt)
00137 *ntmode = p+1;
00138 else
00139 qi->QI_ELEMENT(bearer_capability) = p - (unsigned char *)qi - sizeof(Q931_info_t);
00140 p[0] = IE_BEARER;
00141 p[1] = l;
00142 p[2] = 0x80 + (coding<<5) + capability;
00143 p[3] = 0x80 + (mode<<5) + rate;
00144 if (multi >= 0)
00145 p[4] = 0x80 + multi;
00146 if (user >= 0)
00147 p[4+(multi>=0)] = 0xa0 + user;
00148 }
00149
00150 static void dec_ie_bearer(unsigned char *p, Q931_info_t *qi, int *coding, int *capability, int *mode, int *rate, int *multi, int *user,
00151 int *async, int *urate, int *stopbits, int *dbits, int *parity, int nt, struct misdn_bchannel *bc)
00152 {
00153 int octet;
00154 *coding = -1;
00155 *capability = -1;
00156 *mode = -1;
00157 *rate = -1;
00158 *multi = -1;
00159 *user = -1;
00160 *async = -1;
00161 *urate = -1;
00162 *stopbits = -1;
00163 *dbits = -1;
00164 *parity = -1;
00165
00166 if (!nt)
00167 {
00168 p = NULL;
00169 #ifdef LLC_SUPPORT
00170 if (qi->QI_ELEMENT(llc)) {
00171
00172 p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(llc) + 1;
00173 }
00174 #endif
00175 if (qi->QI_ELEMENT(bearer_capability))
00176 p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(bearer_capability) + 1;
00177 }
00178 if (!p)
00179 return;
00180
00181 if (p[0] < 2)
00182 {
00183 printf("%s: ERROR: IE too short (%d).\n", __FUNCTION__, p[0]);
00184 return;
00185 }
00186
00187 *coding = (p[1]&0x60) >> 5;
00188 *capability = p[1] & 0x1f;
00189 octet = 2;
00190 if (!(p[1] & 0x80))
00191 octet++;
00192
00193 if (p[0] < octet)
00194 goto done;
00195
00196 *mode = (p[octet]&0x60) >> 5;
00197 *rate = p[octet] & 0x1f;
00198
00199 octet++;
00200
00201 if (p[0] < octet)
00202 goto done;
00203
00204 if (*rate == 0x18) {
00205
00206 *multi = p[octet++] & 0x7f;
00207 }
00208
00209 if (p[0] < octet)
00210 goto done;
00211
00212
00213 if ((p[octet] & 0x60) == 0x20) {
00214 *user = p[octet] & 0x1f;
00215
00216 if (p[0] <= octet)
00217 goto done;
00218
00219 if (p[octet++] & 0x80)
00220 goto l2;
00221
00222 *async = !!(p[octet] & 0x40);
00223
00224 *urate = p[octet] & 0x1f;
00225
00226 if (p[0] <= octet)
00227 goto done;
00228
00229 if (p[octet++] & 0x80)
00230 goto l2;
00231
00232
00233
00234 if (p[0] <= octet)
00235 goto done;
00236
00237 if (p[octet++] & 0x80)
00238 goto l2;
00239
00240
00241
00242 if (p[0] <= octet)
00243 goto done;
00244
00245 if (~p[octet++] & 0x80)
00246 goto l2;
00247
00248
00249
00250 *stopbits = (p[octet] & 0x60) >> 5;
00251 *dbits = (p[octet] & 0x18) >> 3;
00252 *parity = p[octet] & 7;
00253
00254 octet++;
00255 }
00256 l2:
00257 done:
00258 if (MISDN_IE_DEBG) printf(" coding=%d capability=%d mode=%d rate=%d multi=%d user=%d async=%d urate=%d stopbits=%d dbits=%d parity=%d\n", *coding, *capability, *mode, *rate, *multi, *user, *async, *urate, *stopbits, *dbits, *parity);
00259 }
00260
00261
00262
00263 #if 0
00264 static void enc_ie_call_id(unsigned char **ntmode, msg_t *msg, char *callid, int callid_len, int nt, struct misdn_bchannel *bc)
00265 {
00266 unsigned char *p;
00267 Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
00268 int l;
00269
00270 char debug[25];
00271 int i;
00272
00273 if (!callid || callid_len<=0)
00274 {
00275 return;
00276 }
00277 if (callid_len>8)
00278 {
00279 printf("%s: ERROR: callid_len(%d) is out of range.\n", __FUNCTION__, callid_len);
00280 return;
00281 }
00282
00283 i = 0;
00284 while(i < callid_len)
00285 {
00286 if (MISDN_IE_DEBG) printf(debug+(i*3), " %02x", callid[i]);
00287 i++;
00288 }
00289
00290 if (MISDN_IE_DEBG) printf(" callid%s\n", debug);
00291
00292 l = callid_len;
00293 p = msg_put(msg, l+2);
00294 if (nt)
00295 *ntmode = p+1;
00296 else
00297 qi->QI_ELEMENT(call_id) = p - (unsigned char *)qi - sizeof(Q931_info_t);
00298 p[0] = IE_CALL_ID;
00299 p[1] = l;
00300 memcpy(p+2, callid, callid_len);
00301 }
00302 #endif
00303
00304 #if 0
00305 static void dec_ie_call_id(unsigned char *p, Q931_info_t *qi, char *callid, int *callid_len, int nt, struct misdn_bchannel *bc)
00306 {
00307 char debug[25];
00308 int i;
00309
00310 *callid_len = -1;
00311
00312 if (!nt)
00313 {
00314 p = NULL;
00315 if (qi->QI_ELEMENT(call_id))
00316 p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(call_id) + 1;
00317 }
00318 if (!p)
00319 return;
00320 if (p[0] > 8)
00321 {
00322 printf("%s: ERROR: IE too long (%d).\n", __FUNCTION__, p[0]);
00323 return;
00324 }
00325
00326 *callid_len = p[0];
00327 memcpy(callid, p+1, *callid_len);
00328
00329 i = 0;
00330 while(i < *callid_len)
00331 {
00332 if (MISDN_IE_DEBG) printf(debug+(i*3), " %02x", callid[i]);
00333 i++;
00334 }
00335
00336 if (MISDN_IE_DEBG) printf(" callid%s\n", debug);
00337 }
00338 #endif
00339
00340
00341 static void enc_ie_called_pn(unsigned char **ntmode, msg_t *msg, int type, int plan, char *number, int nt, struct misdn_bchannel *bc)
00342 {
00343 unsigned char *p;
00344 Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
00345 int l;
00346
00347 if (type<0 || type>7)
00348 {
00349 printf("%s: ERROR: type(%d) is out of range.\n", __FUNCTION__, type);
00350 return;
00351 }
00352 if (plan<0 || plan>15)
00353 {
00354 printf("%s: ERROR: plan(%d) is out of range.\n", __FUNCTION__, plan);
00355 return;
00356 }
00357 if (!number[0])
00358 {
00359 printf("%s: ERROR: number is not given.\n", __FUNCTION__);
00360 return;
00361 }
00362
00363 if (MISDN_IE_DEBG) printf(" type=%d plan=%d number='%s'\n", type, plan, number);
00364
00365 l = 1+strlen((char *)number);
00366 p = msg_put(msg, l+2);
00367 if (nt)
00368 *ntmode = p+1;
00369 else
00370 qi->QI_ELEMENT(called_nr) = p - (unsigned char *)qi - sizeof(Q931_info_t);
00371 p[0] = IE_CALLED_PN;
00372 p[1] = l;
00373 p[2] = 0x80 + (type<<4) + plan;
00374 strncpy((char *)p+3, (char *)number, strlen((char *)number));
00375 }
00376
00377 static void dec_ie_called_pn(unsigned char *p, Q931_info_t *qi, int *type, int *plan, char *number, int number_len, int nt, struct misdn_bchannel *bc)
00378 {
00379 *type = -1;
00380 *plan = -1;
00381 *number = '\0';
00382
00383 if (!nt)
00384 {
00385 p = NULL;
00386 if (qi->QI_ELEMENT(called_nr))
00387 p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(called_nr) + 1;
00388 }
00389 if (!p)
00390 return;
00391 if (p[0] < 2)
00392 {
00393 printf("%s: ERROR: IE too short (%d).\n", __FUNCTION__, p[0]);
00394 return;
00395 }
00396
00397 *type = (p[1]&0x70) >> 4;
00398 *plan = p[1] & 0xf;
00399 strnncpy(number, (char *)p+2, p[0]-1, number_len);
00400
00401 if (MISDN_IE_DEBG) printf(" type=%d plan=%d number='%s'\n", *type, *plan, number);
00402 }
00403
00404
00405
00406 static void enc_ie_calling_pn(unsigned char **ntmode, msg_t *msg, int type, int plan, int present, int screen, char *number, int nt, struct misdn_bchannel *bc)
00407 {
00408 unsigned char *p;
00409 Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
00410 int l;
00411
00412 if (type<0 || type>7)
00413 {
00414 printf("%s: ERROR: type(%d) is out of range.\n", __FUNCTION__, type);
00415 return;
00416 }
00417 if (plan<0 || plan>15)
00418 {
00419 printf("%s: ERROR: plan(%d) is out of range.\n", __FUNCTION__, plan);
00420 return;
00421 }
00422 if (present>3)
00423 {
00424 printf("%s: ERROR: present(%d) is out of range.\n", __FUNCTION__, present);
00425 return;
00426 }
00427 if (present >= 0) if (screen<0 || screen>3)
00428 {
00429 printf("%s: ERROR: screen(%d) is out of range.\n", __FUNCTION__, screen);
00430 return;
00431 }
00432
00433 if (MISDN_IE_DEBG) printf(" type=%d plan=%d present=%d screen=%d number='%s'\n", type, plan, present, screen, number);
00434
00435 l = 1;
00436 if (number) if (number[0])
00437 l += strlen((char *)number);
00438 if (present >= 0)
00439 l += 1;
00440 p = msg_put(msg, l+2);
00441 if (nt)
00442 *ntmode = p+1;
00443 else
00444 qi->QI_ELEMENT(calling_nr) = p - (unsigned char *)qi - sizeof(Q931_info_t);
00445 p[0] = IE_CALLING_PN;
00446 p[1] = l;
00447 if (present >= 0)
00448 {
00449 p[2] = 0x00 + (type<<4) + plan;
00450 p[3] = 0x80 + (present<<5) + screen;
00451 if (number) if (number[0])
00452 strncpy((char *)p+4, (char *)number, strlen((char *)number));
00453 } else
00454 {
00455 p[2] = 0x80 + (type<<4) + plan;
00456 if (number) if (number[0])
00457 strncpy((char *)p+3, (char *)number, strlen((char *)number));
00458 }
00459 }
00460
00461 static void dec_ie_calling_pn(unsigned char *p, Q931_info_t *qi, int *type, int *plan, int *present, int *screen, char *number, int number_len, int nt, struct misdn_bchannel *bc)
00462 {
00463 *type = -1;
00464 *plan = -1;
00465 *present = -1;
00466 *screen = -1;
00467 *number = '\0';
00468
00469 if (!nt)
00470 {
00471 p = NULL;
00472 if (qi->QI_ELEMENT(calling_nr))
00473 p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(calling_nr) + 1;
00474 }
00475 if (!p)
00476 return;
00477 if (p[0] < 1)
00478 {
00479 printf("%s: ERROR: IE too short (%d).\n", __FUNCTION__, p[0]);
00480 return;
00481 }
00482
00483 *type = (p[1]&0x70) >> 4;
00484 *plan = p[1] & 0xf;
00485 if (!(p[1] & 0x80))
00486 {
00487 if (p[0] < 2)
00488 {
00489 printf("%s: ERROR: IE too short (%d).\n", __FUNCTION__, p[0]);
00490 return;
00491 }
00492 *present = (p[2]&0x60) >> 5;
00493 *screen = p[2] & 0x3;
00494 strnncpy(number, (char *)p+3, p[0]-2, number_len);
00495 } else
00496 {
00497 strnncpy(number, (char *)p+2, p[0]-1, number_len);
00498
00499
00500
00501 }
00502
00503 if (MISDN_IE_DEBG) printf(" type=%d plan=%d present=%d screen=%d number='%s'\n", *type, *plan, *present, *screen, number);
00504 }
00505
00506
00507
00508 static void enc_ie_connected_pn(unsigned char **ntmode, msg_t *msg, int type, int plan, int present, int screen, char *number, int nt, struct misdn_bchannel *bc)
00509 {
00510 unsigned char *p;
00511 Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
00512 int l;
00513
00514 if (type<0 || type>7)
00515 {
00516 printf("%s: ERROR: type(%d) is out of range.\n", __FUNCTION__, type);
00517 return;
00518 }
00519 if (plan<0 || plan>15)
00520 {
00521 printf("%s: ERROR: plan(%d) is out of range.\n", __FUNCTION__, plan);
00522 return;
00523 }
00524 if (present>3)
00525 {
00526 printf("%s: ERROR: present(%d) is out of range.\n", __FUNCTION__, present);
00527 return;
00528 }
00529 if (present >= 0) if (screen<0 || screen>3)
00530 {
00531 printf("%s: ERROR: screen(%d) is out of range.\n", __FUNCTION__, screen);
00532 return;
00533 }
00534
00535 if (MISDN_IE_DEBG) printf(" type=%d plan=%d present=%d screen=%d number='%s'\n", type, plan, present, screen, number);
00536
00537 l = 1;
00538 if (number) if (number[0])
00539 l += strlen((char *)number);
00540 if (present >= 0)
00541 l += 1;
00542 p = msg_put(msg, l+2);
00543 if (nt)
00544 *ntmode = p+1;
00545 else
00546 qi->QI_ELEMENT(connected_nr) = p - (unsigned char *)qi - sizeof(Q931_info_t);
00547 p[0] = IE_CONNECT_PN;
00548 p[1] = l;
00549 if (present >= 0)
00550 {
00551 p[2] = 0x00 + (type<<4) + plan;
00552 p[3] = 0x80 + (present<<5) + screen;
00553 if (number) if (number[0])
00554 strncpy((char *)p+4, (char *)number, strlen((char *)number));
00555 } else
00556 {
00557 p[2] = 0x80 + (type<<4) + plan;
00558 if (number) if (number[0])
00559 strncpy((char *)p+3, (char *)number, strlen((char *)number));
00560 }
00561 }
00562
00563 static void dec_ie_connected_pn(unsigned char *p, Q931_info_t *qi, int *type, int *plan, int *present, int *screen, char *number, int number_len, int nt, struct misdn_bchannel *bc)
00564 {
00565 *type = -1;
00566 *plan = -1;
00567 *present = -1;
00568 *screen = -1;
00569 *number = '\0';
00570
00571 if (!nt)
00572 {
00573 p = NULL;
00574 if (qi->QI_ELEMENT(connected_nr))
00575 p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(connected_nr) + 1;
00576 }
00577 if (!p)
00578 return;
00579 if (p[0] < 1)
00580 {
00581 printf("%s: ERROR: IE too short (%d).\n", __FUNCTION__, p[0]);
00582 return;
00583 }
00584
00585 *type = (p[1]&0x70) >> 4;
00586 *plan = p[1] & 0xf;
00587 if (!(p[1] & 0x80))
00588 {
00589 if (p[0] < 2)
00590 {
00591 printf("%s: ERROR: IE too short (%d).\n", __FUNCTION__, p[0]);
00592 return;
00593 }
00594 *present = (p[2]&0x60) >> 5;
00595 *screen = p[2] & 0x3;
00596 strnncpy(number, (char *)p+3, p[0]-2, number_len);
00597 } else
00598 {
00599 strnncpy(number, (char *)p+2, p[0]-1, number_len);
00600 }
00601
00602 if (MISDN_IE_DEBG) printf(" type=%d plan=%d present=%d screen=%d number='%s'\n", *type, *plan, *present, *screen, number);
00603 }
00604
00605
00606
00607 static void enc_ie_cause(unsigned char **ntmode, msg_t *msg, int location, int cause, int nt, struct misdn_bchannel *bc)
00608 {
00609 unsigned char *p;
00610 Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
00611 int l;
00612
00613 if (location<0 || location>7)
00614 {
00615 printf("%s: ERROR: location(%d) is out of range.\n", __FUNCTION__, location);
00616 return;
00617 }
00618 if (cause<0 || cause>127)
00619 {
00620 printf("%s: ERROR: cause(%d) is out of range.\n", __FUNCTION__, cause);
00621 return;
00622 }
00623
00624 if (MISDN_IE_DEBG) printf(" location=%d cause=%d\n", location, cause);
00625
00626 l = 2;
00627 p = msg_put(msg, l+2);
00628 if (nt)
00629 *ntmode = p+1;
00630 else
00631 qi->QI_ELEMENT(cause) = p - (unsigned char *)qi - sizeof(Q931_info_t);
00632 p[0] = IE_CAUSE;
00633 p[1] = l;
00634 p[2] = 0x80 + location;
00635 p[3] = 0x80 + cause;
00636 }
00637
00638 #if 0
00639 static void enc_ie_cause_standalone(unsigned char **ntmode, msg_t *msg, int location, int cause, int nt, struct misdn_bchannel *bc)
00640 {
00641 unsigned char *p = msg_put(msg, 4);
00642 Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
00643 if (ntmode)
00644 *ntmode = p+1;
00645 else
00646 qi->QI_ELEMENT(cause) = p - (unsigned char *)qi - sizeof(Q931_info_t);
00647 p[0] = IE_CAUSE;
00648 p[1] = 2;
00649 p[2] = 0x80 + location;
00650 p[3] = 0x80 + cause;
00651 }
00652 #endif
00653
00654 static void dec_ie_cause(unsigned char *p, Q931_info_t *qi, int *location, int *cause, int nt, struct misdn_bchannel *bc)
00655 {
00656 *location = -1;
00657 *cause = -1;
00658
00659 if (!nt)
00660 {
00661 p = NULL;
00662 if (qi->QI_ELEMENT(cause))
00663 p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(cause) + 1;
00664 }
00665 if (!p)
00666 return;
00667 if (p[0] < 2)
00668 {
00669 printf("%s: ERROR: IE too short (%d).\n", __FUNCTION__, p[0]);
00670 return;
00671 }
00672
00673 *location = p[1] & 0x0f;
00674 *cause = p[2] & 0x7f;
00675
00676 if (MISDN_IE_DEBG) printf(" location=%d cause=%d\n", *location, *cause);
00677 }
00678
00679
00680
00681 static void enc_ie_channel_id(unsigned char **ntmode, msg_t *msg, int exclusive, int channel, int nt, struct misdn_bchannel *bc)
00682 {
00683 unsigned char *p;
00684 Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
00685 int l;
00686 struct misdn_stack *stack=get_stack_by_bc(bc);
00687 int pri = stack->pri;
00688
00689 if (exclusive<0 || exclusive>1)
00690 {
00691 printf("%s: ERROR: exclusive(%d) is out of range.\n", __FUNCTION__, exclusive);
00692 return;
00693 }
00694 if ((channel<0 || channel>0xff)
00695 || (!pri && (channel>2 && channel<0xff))
00696 || (pri && (channel>31 && channel<0xff))
00697 || (pri && channel==16))
00698 {
00699 printf("%s: ERROR: channel(%d) is out of range.\n", __FUNCTION__, channel);
00700 return;
00701 }
00702
00703
00704
00705
00706 if (!pri)
00707 {
00708
00709 l = 1;
00710 p = msg_put(msg, l+2);
00711 if (nt)
00712 *ntmode = p+1;
00713 else
00714 qi->QI_ELEMENT(channel_id) = p - (unsigned char *)qi - sizeof(Q931_info_t);
00715 p[0] = IE_CHANNEL_ID;
00716 p[1] = l;
00717 if (channel == 0xff)
00718 channel = 3;
00719 p[2] = 0x80 + (exclusive<<3) + channel;
00720
00721 } else
00722 {
00723
00724 if (channel == 0)
00725 return;
00726
00727 if (channel == 0xff)
00728 {
00729 l = 1;
00730 p = msg_put(msg, l+2);
00731 if (nt)
00732 *ntmode = p+1;
00733 else
00734 qi->QI_ELEMENT(channel_id) = p - (unsigned char *)qi - sizeof(Q931_info_t);
00735 p[0] = IE_CHANNEL_ID;
00736 p[1] = l;
00737 p[2] = 0x80 + 0x20 + 0x03;
00738
00739 return;
00740 }
00741 l = 3;
00742 p = msg_put(msg, l+2);
00743 if (nt)
00744 *ntmode = p+1;
00745 else
00746 qi->QI_ELEMENT(channel_id) = p - (unsigned char *)qi - sizeof(Q931_info_t);
00747 p[0] = IE_CHANNEL_ID;
00748 p[1] = l;
00749 p[2] = 0x80 + 0x20 + (exclusive<<3) + 0x01;
00750 p[3] = 0x80 + 3;
00751 p[4] = 0x80 + channel;
00752
00753 }
00754 }
00755
00756 static void dec_ie_channel_id(unsigned char *p, Q931_info_t *qi, int *exclusive, int *channel, int nt, struct misdn_bchannel *bc)
00757 {
00758 struct misdn_stack *stack=get_stack_by_bc(bc);
00759 int pri =stack->pri;
00760
00761 *exclusive = -1;
00762 *channel = -1;
00763
00764 if (!nt)
00765 {
00766 p = NULL;
00767 if (qi->QI_ELEMENT(channel_id))
00768 p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(channel_id) + 1;
00769 }
00770 if (!p)
00771 return;
00772 if (p[0] < 1)
00773 {
00774 printf("%s: ERROR: IE too short (%d).\n", __FUNCTION__, p[0]);
00775 return;
00776 }
00777
00778 if (p[1] & 0x40)
00779 {
00780 printf("%s: ERROR: refering to channels of other interfaces is not supported.\n", __FUNCTION__);
00781 return;
00782 }
00783 if (p[1] & 0x04)
00784 {
00785 printf("%s: ERROR: using d-channel is not supported.\n", __FUNCTION__);
00786 return;
00787 }
00788
00789 *exclusive = (p[1]&0x08) >> 3;
00790 if (!pri)
00791 {
00792
00793 if (p[1] & 0x20)
00794 {
00795 printf("%s: ERROR: extended channel ID with non PRI interface.\n", __FUNCTION__);
00796 return;
00797 }
00798 *channel = p[1] & 0x03;
00799 if (*channel == 3)
00800 *channel = 0xff;
00801 } else
00802 {
00803
00804 if (p[0] < 1)
00805 {
00806 printf("%s: ERROR: IE too short for PRI (%d).\n", __FUNCTION__, p[0]);
00807 return;
00808 }
00809 if (!(p[1] & 0x20))
00810 {
00811 printf("%s: ERROR: basic channel ID with PRI interface.\n", __FUNCTION__);
00812 return;
00813 }
00814 if ((p[1]&0x03) == 0x00)
00815 {
00816
00817 *channel = 0;
00818 return;
00819 }
00820 if ((p[1]&0x03) == 0x03)
00821 {
00822
00823 *channel = 0xff;
00824 return;
00825 }
00826 if (p[0] < 3)
00827 {
00828 printf("%s: ERROR: IE too short for PRI with channel(%d).\n", __FUNCTION__, p[0]);
00829 return;
00830 }
00831 if (p[2] & 0x10)
00832 {
00833 printf("%s: ERROR: channel map not supported.\n", __FUNCTION__);
00834 return;
00835 }
00836 *channel = p[3] & 0x7f;
00837 if ( (*channel<1) | (*channel==16) | (*channel>31))
00838 {
00839 printf("%s: ERROR: PRI interface channel out of range (%d).\n", __FUNCTION__, *channel);
00840 return;
00841 }
00842
00843 }
00844
00845 if (MISDN_IE_DEBG) printf(" exclusive=%d channel=%d\n", *exclusive, *channel);
00846 }
00847
00848
00849
00850 static void enc_ie_date(unsigned char **ntmode, msg_t *msg, time_t ti, int nt, struct misdn_bchannel *bc)
00851 {
00852 unsigned char *p;
00853 Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
00854 int l;
00855
00856 struct tm *tm;
00857
00858 tm = localtime(&ti);
00859 if (!tm)
00860 {
00861 printf("%s: ERROR: gettimeofday() returned NULL.\n", __FUNCTION__);
00862 return;
00863 }
00864
00865 if (MISDN_IE_DEBG) printf(" year=%d month=%d day=%d hour=%d minute=%d\n", tm->tm_year%100, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min);
00866
00867 l = 5;
00868 p = msg_put(msg, l+2);
00869 if (nt)
00870 *ntmode = p+1;
00871 else
00872 qi->QI_ELEMENT(date) = p - (unsigned char *)qi - sizeof(Q931_info_t);
00873 p[0] = IE_DATE;
00874 p[1] = l;
00875 p[2] = tm->tm_year % 100;
00876 p[3] = tm->tm_mon + 1;
00877 p[4] = tm->tm_mday;
00878 p[5] = tm->tm_hour;
00879 p[6] = tm->tm_min;
00880 }
00881
00882
00883
00884 static void enc_ie_display(unsigned char **ntmode, msg_t *msg, char *display, int nt, struct misdn_bchannel *bc)
00885 {
00886 unsigned char *p;
00887 Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
00888 int l;
00889
00890 if (!display[0])
00891 {
00892 printf("%s: ERROR: display text not given.\n", __FUNCTION__);
00893 return;
00894 }
00895
00896 if (strlen((char *)display) > 80)
00897 {
00898 printf("%s: WARNING: display text too long (max 80 chars), cutting.\n", __FUNCTION__);
00899 display[80] = '\0';
00900 }
00901
00902
00903
00904 l = strlen((char *)display);
00905 p = msg_put(msg, l+2);
00906 if (nt)
00907 *ntmode = p+1;
00908 else
00909 qi->QI_ELEMENT(display) = p - (unsigned char *)qi - sizeof(Q931_info_t);
00910 p[0] = IE_DISPLAY;
00911 p[1] = l;
00912 strncpy((char *)p+2, (char *)display, strlen((char *)display));
00913 }
00914
00915 #if 0
00916 static void dec_ie_display(unsigned char *p, Q931_info_t *qi, char *display, int display_len, int nt, struct misdn_bchannel *bc)
00917 {
00918 *display = '\0';
00919
00920 if (!nt)
00921 {
00922 p = NULL;
00923 if (qi->QI_ELEMENT(display))
00924 p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(display) + 1;
00925 }
00926 if (!p)
00927 return;
00928 if (p[0] < 1)
00929 {
00930 printf("%s: ERROR: IE too short (%d).\n", __FUNCTION__, p[0]);
00931 return;
00932 }
00933
00934 strnncpy(display, (char *)p+1, p[0], display_len);
00935
00936 if (MISDN_IE_DEBG) printf(" display='%s'\n", display);
00937 }
00938 #endif
00939
00940
00941 #if 1
00942 static void enc_ie_keypad(unsigned char **ntmode, msg_t *msg, char *keypad, int nt, struct misdn_bchannel *bc)
00943 {
00944 unsigned char *p;
00945 Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
00946 int l;
00947
00948 if (!keypad[0])
00949 {
00950 printf("%s: ERROR: keypad info not given.\n", __FUNCTION__);
00951 return;
00952 }
00953
00954 if (MISDN_IE_DEBG) printf(" keypad='%s'\n", keypad);
00955
00956 l = strlen(keypad);
00957 p = msg_put(msg, l+2);
00958 if (nt)
00959 *ntmode = p+1;
00960 else
00961 qi->QI_ELEMENT(keypad) = p - (unsigned char *)qi - sizeof(Q931_info_t);
00962 p[0] = IE_KEYPAD;
00963 p[1] = l;
00964 strncpy((char *)p+2, keypad, strlen(keypad));
00965 }
00966 #endif
00967
00968 static void dec_ie_keypad(unsigned char *p, Q931_info_t *qi, char *keypad, int keypad_len, int nt, struct misdn_bchannel *bc)
00969 {
00970 *keypad = '\0';
00971
00972 if (!nt)
00973 {
00974 p = NULL;
00975 if (qi->QI_ELEMENT(keypad))
00976 p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(keypad) + 1;
00977 }
00978 if (!p)
00979 return;
00980 if (p[0] < 1)
00981 {
00982 printf("%s: ERROR: IE too short (%d).\n", __FUNCTION__, p[0]);
00983 return;
00984 }
00985
00986 strnncpy(keypad, (char *)p+1, p[0], keypad_len);
00987
00988 if (MISDN_IE_DEBG) printf(" keypad='%s'\n", keypad);
00989 }
00990
00991
00992
00993 #if 0
00994 static void enc_ie_notify(unsigned char **ntmode, msg_t *msg, int notify, int nt, struct misdn_bchannel *bc)
00995 {
00996 unsigned char *p;
00997 Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
00998 int l;
00999
01000 if (notify<0 || notify>0x7f)
01001 {
01002 printf("%s: ERROR: notify(%d) is out of range.\n", __FUNCTION__, notify);
01003 return;
01004 }
01005
01006 if (MISDN_IE_DEBG) printf(" notify=%d\n", notify);
01007
01008 l = 1;
01009 p = msg_put(msg, l+2);
01010 if (nt)
01011 *ntmode = p+1;
01012 else
01013 qi->QI_ELEMENT(notify) = p - (unsigned char *)qi - sizeof(Q931_info_t);
01014 p[0] = IE_NOTIFY;
01015 p[1] = l;
01016 p[2] = 0x80 + notify;
01017 }
01018 #endif
01019
01020 #if 0
01021 static void dec_ie_notify(unsigned char *p, Q931_info_t *qi, int *notify, int nt, struct misdn_bchannel *bc)
01022 {
01023 *notify = -1;
01024
01025 if (!nt)
01026 {
01027 p = NULL;
01028 if (qi->QI_ELEMENT(notify))
01029 p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(notify) + 1;
01030 }
01031 if (!p)
01032 return;
01033 if (p[0] < 1)
01034 {
01035 printf("%s: ERROR: IE too short (%d).\n", __FUNCTION__, p[0]);
01036 return;
01037 }
01038
01039 *notify = p[1] & 0x7f;
01040
01041 if (MISDN_IE_DEBG) printf(" notify=%d\n", *notify);
01042 }
01043 #endif
01044
01045
01046
01047 static void enc_ie_progress(unsigned char **ntmode, msg_t *msg, int coding, int location, int progress, int nt, struct misdn_bchannel *bc)
01048 {
01049 unsigned char *p;
01050 Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
01051 int l;
01052
01053 if (coding<0 || coding>0x03)
01054 {
01055 printf("%s: ERROR: coding(%d) is out of range.\n", __FUNCTION__, coding);
01056 return;
01057 }
01058 if (location<0 || location>0x0f)
01059 {
01060 printf("%s: ERROR: location(%d) is out of range.\n", __FUNCTION__, location);
01061 return;
01062 }
01063 if (progress<0 || progress>0x7f)
01064 {
01065 printf("%s: ERROR: progress(%d) is out of range.\n", __FUNCTION__, progress);
01066 return;
01067 }
01068
01069 if (MISDN_IE_DEBG) printf(" coding=%d location=%d progress=%d\n", coding, location, progress);
01070
01071 l = 2;
01072 p = msg_put(msg, l+2);
01073 if (nt)
01074 *ntmode = p+1;
01075 else
01076 qi->QI_ELEMENT(progress) = p - (unsigned char *)qi - sizeof(Q931_info_t);
01077 p[0] = IE_PROGRESS;
01078 p[1] = l;
01079 p[2] = 0x80 + (coding<<5) + location;
01080 p[3] = 0x80 + progress;
01081 }
01082
01083 static void dec_ie_progress(unsigned char *p, Q931_info_t *qi, int *coding, int *location, int *progress, int nt, struct misdn_bchannel *bc)
01084 {
01085 *coding = -1;
01086 *location = -1;
01087
01088 *progress = 0;
01089
01090 if (!nt)
01091 {
01092 p = NULL;
01093 if (qi->QI_ELEMENT(progress))
01094 p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(progress) + 1;
01095 }
01096 if (!p)
01097 return;
01098 if (p[0] < 1)
01099 {
01100 printf("%s: ERROR: IE too short (%d).\n", __FUNCTION__, p[0]);
01101 return;
01102 }
01103
01104 *coding = (p[1]&0x60) >> 5;
01105 *location = p[1] & 0x0f;
01106 *progress = p[2] & 0x7f;
01107
01108 if (MISDN_IE_DEBG) printf(" coding=%d location=%d progress=%d\n", *coding, *location, *progress);
01109 }
01110
01111
01112
01113 static void enc_ie_redir_nr(unsigned char **ntmode, msg_t *msg, int type, int plan, int present, int screen, int reason, char *number, int nt, struct misdn_bchannel *bc)
01114 {
01115 unsigned char *p;
01116 Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
01117 int l;
01118
01119 if (type<0 || type>7)
01120 {
01121 printf("%s: ERROR: type(%d) is out of range.\n", __FUNCTION__, type);
01122 return;
01123 }
01124 if (plan<0 || plan>15)
01125 {
01126 printf("%s: ERROR: plan(%d) is out of range.\n", __FUNCTION__, plan);
01127 return;
01128 }
01129 if (present > 3)
01130 {
01131 printf("%s: ERROR: present(%d) is out of range.\n", __FUNCTION__, present);
01132 return;
01133 }
01134 if (present >= 0) if (screen<0 || screen>3)
01135 {
01136 printf("%s: ERROR: screen(%d) is out of range.\n", __FUNCTION__, screen);
01137 return;
01138 }
01139 if (reason > 0x0f)
01140 {
01141 printf("%s: ERROR: reason(%d) is out of range.\n", __FUNCTION__, reason);
01142 return;
01143 }
01144
01145 if (MISDN_IE_DEBG) printf(" type=%d plan=%d present=%d screen=%d readon=%d number='%s'\n", type, plan, present, screen, reason, number);
01146
01147 l = 1;
01148 if (number)
01149 l += strlen((char *)number);
01150 if (present >= 0)
01151 {
01152 l += 1;
01153 if (reason >= 0)
01154 l += 1;
01155 }
01156 p = msg_put(msg, l+2);
01157 if (nt)
01158 *ntmode = p+1;
01159 else
01160 qi->QI_ELEMENT(redirect_nr) = p - (unsigned char *)qi - sizeof(Q931_info_t);
01161 p[0] = IE_REDIR_NR;
01162 p[1] = l;
01163 if (present >= 0)
01164 {
01165 if (reason >= 0)
01166 {
01167 p[2] = 0x00 + (type<<4) + plan;
01168 p[3] = 0x00 + (present<<5) + screen;
01169 p[4] = 0x80 + reason;
01170 if (number)
01171 strncpy((char *)p+5, (char *)number, strlen((char *)number));
01172 } else
01173 {
01174 p[2] = 0x00 + (type<<4) + plan;
01175 p[3] = 0x80 + (present<<5) + screen;
01176 if (number)
01177 strncpy((char *)p+4, (char *)number, strlen((char *)number));
01178 }
01179 } else
01180 {
01181 p[2] = 0x80 + (type<<4) + plan;
01182 if (number) if (number[0])
01183 strncpy((char *)p+3, (char *)number, strlen((char *)number));
01184 }
01185 }
01186
01187 static void dec_ie_redir_nr(unsigned char *p, Q931_info_t *qi, int *type, int *plan, int *present, int *screen, int *reason, char *number, int number_len, int nt, struct misdn_bchannel *bc)
01188 {
01189 *type = -1;
01190 *plan = -1;
01191 *present = -1;
01192 *screen = -1;
01193 *reason = -1;
01194 *number = '\0';
01195
01196 if (!nt)
01197 {
01198 p = NULL;
01199 if (qi->QI_ELEMENT(redirect_nr))
01200 p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(redirect_nr) + 1;
01201 }
01202 if (!p)
01203 return;
01204 if (p[0] < 1)
01205 {
01206 printf("%s: ERROR: IE too short (%d).\n", __FUNCTION__, p[0]);
01207 return;
01208 }
01209
01210 *type = (p[1]&0x70) >> 4;
01211 *plan = p[1] & 0xf;
01212 if (!(p[1] & 0x80))
01213 {
01214 *present = (p[2]&0x60) >> 5;
01215 *screen = p[2] & 0x3;
01216 if (!(p[2] & 0x80))
01217 {
01218 *reason = p[3] & 0x0f;
01219 strnncpy(number, (char *)p+4, p[0]-3, number_len);
01220 } else
01221 {
01222 strnncpy(number, (char *)p+3, p[0]-2, number_len);
01223 }
01224 } else
01225 {
01226 strnncpy(number, (char *)p+2, p[0]-1, number_len);
01227 }
01228
01229 if (MISDN_IE_DEBG) printf(" type=%d plan=%d present=%d screen=%d reason=%d number='%s'\n", *type, *plan, *present, *screen, *reason, number);
01230 }
01231
01232
01233
01234 #if 0
01235 static void enc_ie_redir_dn(unsigned char **ntmode, msg_t *msg, int type, int plan, int present, char *number, int nt, struct misdn_bchannel *bc)
01236 {
01237 unsigned char *p;
01238
01239 int l;
01240
01241 if (type<0 || type>7)
01242 {
01243 printf("%s: ERROR: type(%d) is out of range.\n", __FUNCTION__, type);
01244 return;
01245 }
01246 if (plan<0 || plan>15)
01247 {
01248 printf("%s: ERROR: plan(%d) is out of range.\n", __FUNCTION__, plan);
01249 return;
01250 }
01251 if (present > 3)
01252 {
01253 printf("%s: ERROR: present(%d) is out of range.\n", __FUNCTION__, present);
01254 return;
01255 }
01256
01257 if (MISDN_IE_DEBG) printf(" type=%d plan=%d present=%d number='%s'\n", type, plan, present, number);
01258
01259 l = 1;
01260 if (number)
01261 l += strlen((char *)number);
01262 if (present >= 0)
01263 l += 1;
01264 p = msg_put(msg, l+2);
01265 if (nt)
01266 *ntmode = p+1;
01267 else
01268
01269 ;
01270 p[0] = IE_REDIR_DN;
01271 p[1] = l;
01272 if (present >= 0)
01273 {
01274 p[2] = 0x00 + (type<<4) + plan;
01275 p[3] = 0x80 + (present<<5);
01276 if (number)
01277 strncpy((char *)p+4, (char *)number, strlen((char *)number));
01278 } else
01279 {
01280 p[2] = 0x80 + (type<<4) + plan;
01281 if (number)
01282 strncpy((char *)p+3, (char *)number, strlen((char *)number));
01283 }
01284 }
01285 #endif
01286
01287 #if 0
01288 static void dec_ie_redir_dn(unsigned char *p, Q931_info_t *qi, int *type, int *plan, int *present, char *number, int number_len, int nt, struct misdn_bchannel *bc)
01289 {
01290 *type = -1;
01291 *plan = -1;
01292 *present = -1;
01293 *number = '\0';
01294
01295 if (!nt)
01296 {
01297 p = NULL;
01298
01299
01300
01301 }
01302 if (!p)
01303 return;
01304 if (p[0] < 1)
01305 {
01306 printf("%s: ERROR: IE too short (%d).\n", __FUNCTION__, p[0]);
01307 return;
01308 }
01309
01310 *type = (p[1]&0x70) >> 4;
01311 *plan = p[1] & 0xf;
01312 if (!(p[1] & 0x80))
01313 {
01314 *present = (p[2]&0x60) >> 5;
01315 strnncpy(number, (char *)p+3, p[0]-2, number_len);
01316 } else
01317 {
01318 strnncpy(number, (char *)p+2, p[0]-1, number_len);
01319 }
01320
01321 if (MISDN_IE_DEBG) printf(" type=%d plan=%d present=%d number='%s'\n", *type, *plan, *present, number);
01322 }
01323 #endif
01324
01325
01326
01327 #if 1
01328 static void enc_ie_useruser(unsigned char **ntmode, msg_t *msg, int protocol, char *user, int user_len, int nt, struct misdn_bchannel *bc)
01329 {
01330 unsigned char *p;
01331 Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
01332 int l;
01333
01334 char debug[768];
01335 int i;
01336
01337 if (protocol<0 || protocol>127)
01338 {
01339 printf("%s: ERROR: protocol(%d) is out of range.\n", __FUNCTION__, protocol);
01340 return;
01341 }
01342 if (!user || user_len<=0)
01343 {
01344 return;
01345 }
01346
01347 i = 0;
01348 while(i < user_len)
01349 {
01350 if (MISDN_IE_DEBG) printf(debug+(i*3), " %02x", user[i]);
01351 i++;
01352 }
01353
01354 if (MISDN_IE_DEBG) printf(" protocol=%d user-user%s\n", protocol, debug);
01355
01356 l = user_len+1;
01357 p = msg_put(msg, l+3);
01358 if (nt)
01359 *ntmode = p+1;
01360 else
01361 qi->QI_ELEMENT(useruser) = p - (unsigned char *)qi - sizeof(Q931_info_t);
01362 p[0] = IE_USER_USER;
01363 p[1] = l;
01364 p[2] = protocol;
01365 memcpy(p+3, user, user_len);
01366 }
01367 #endif
01368
01369 #if 1
01370 static void dec_ie_useruser(unsigned char *p, Q931_info_t *qi, int *protocol, char *user, int *user_len, int nt, struct misdn_bchannel *bc)
01371 {
01372 char debug[768];
01373 int i;
01374
01375 *user_len = 0;
01376 *protocol = -1;
01377
01378 if (!nt)
01379 {
01380 p = NULL;
01381 if (qi->QI_ELEMENT(useruser))
01382 p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(useruser) + 1;
01383 }
01384 if (!p)
01385 return;
01386
01387 *user_len = p[0]-1;
01388 if (p[0] < 1)
01389 return;
01390 *protocol = p[1];
01391 memcpy(user, p+2, (*user_len<=128)?*(user_len):128);
01392
01393 i = 0;
01394 while(i < *user_len)
01395 {
01396 if (MISDN_IE_DEBG) printf(debug+(i*3), " %02x", user[i]);
01397 i++;
01398 }
01399 debug[i*3] = '\0';
01400
01401 if (MISDN_IE_DEBG) printf(" protocol=%d user-user%s\n", *protocol, debug);
01402 }
01403 #endif
01404
01405
01406 static void enc_ie_restart_ind(unsigned char **ntmode, msg_t *msg, unsigned char rind, int nt, struct misdn_bchannel *bc)
01407 {
01408 unsigned char *p;
01409 Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
01410
01411
01412 p = msg_put(msg, 3);
01413 if (nt)
01414 *ntmode = p+1;
01415 else
01416 qi->QI_ELEMENT(restart_ind) = p - (unsigned char *)qi - sizeof(Q931_info_t);
01417 p[0] = IE_RESTART_IND;
01418 p[1] = 1;
01419 p[2] = rind;
01420
01421 }
01422