00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include <string.h>
00030
00031 #include <mISDNuser/mISDNlib.h>
00032 #include <mISDNuser/isdn_net.h>
00033 #include <mISDNuser/l3dss1.h>
00034 #include <mISDNuser/net_l3.h>
00035 #include "asterisk/localtime.h"
00036
00037
00038
00039 #define MISDN_IE_DEBG 0
00040
00041
00042 static void strnncpy(char *dest, char *src, int len, int dst_len)
00043 {
00044 if (len > dst_len-1)
00045 len = dst_len-1;
00046 strncpy((char *)dest, (char *)src, len);
00047 dest[len] = '\0';
00048 }
00049
00050
00051
00052 static void enc_ie_complete(unsigned char **ntmode, msg_t *msg, int complete, int nt, struct misdn_bchannel *bc)
00053 {
00054 unsigned char *p;
00055 Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
00056
00057 if (complete<0 || complete>1)
00058 {
00059 printf("%s: ERROR: complete(%d) is out of range.\n", __FUNCTION__, complete);
00060 return;
00061 }
00062
00063 if (complete)
00064 if (MISDN_IE_DEBG) printf(" complete=%d\n", complete);
00065
00066 if (complete)
00067 {
00068 p = msg_put(msg, 1);
00069 if (nt)
00070 {
00071 *ntmode = p;
00072 } else
00073 qi->QI_ELEMENT(sending_complete) = p - (unsigned char *)qi - sizeof(Q931_info_t);
00074
00075 p[0] = IE_COMPLETE;
00076 }
00077 }
00078
00079 static void dec_ie_complete(unsigned char *p, Q931_info_t *qi, int *complete, int nt, struct misdn_bchannel *bc)
00080 {
00081 *complete = 0;
00082 if (!nt)
00083 {
00084 if (qi->QI_ELEMENT(sending_complete))
00085 *complete = 1;
00086 } else
00087 if (p)
00088 *complete = 1;
00089
00090 if (*complete)
00091 if (MISDN_IE_DEBG) printf(" complete=%d\n", *complete);
00092 }
00093
00094
00095
00096 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)
00097 {
00098 unsigned char *p;
00099 Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
00100 int l;
00101
00102 if (coding<0 || coding>3)
00103 {
00104 printf("%s: ERROR: coding(%d) is out of range.\n", __FUNCTION__, coding);
00105 return;
00106 }
00107 if (capability<0 || capability>31)
00108 {
00109 printf("%s: ERROR: capability(%d) is out of range.\n", __FUNCTION__, capability);
00110 return;
00111 }
00112 if (mode<0 || mode>3)
00113 {
00114 printf("%s: ERROR: mode(%d) is out of range.\n", __FUNCTION__, mode);
00115 return;
00116 }
00117 if (rate<0 || rate>31)
00118 {
00119 printf("%s: ERROR: rate(%d) is out of range.\n", __FUNCTION__, rate);
00120 return;
00121 }
00122 if (multi>127)
00123 {
00124 printf("%s: ERROR: multi(%d) is out of range.\n", __FUNCTION__, multi);
00125 return;
00126 }
00127 if (user>31)
00128 {
00129 printf("%s: ERROR: user L1(%d) is out of range.\n", __FUNCTION__, rate);
00130 return;
00131 }
00132 if (rate!=24 && multi>=0)
00133 {
00134 printf("%s: WARNING: multi(%d) is only possible if rate(%d) would be 24.\n", __FUNCTION__, multi, rate);
00135 multi = -1;
00136 }
00137
00138 if (MISDN_IE_DEBG) printf(" coding=%d capability=%d mode=%d rate=%d multi=%d user=%d\n", coding, capability, mode, rate, multi, user);
00139
00140 l = 2 + (multi>=0) + (user>=0);
00141 p = msg_put(msg, l+2);
00142 if (nt)
00143 *ntmode = p+1;
00144 else
00145 qi->QI_ELEMENT(bearer_capability) = p - (unsigned char *)qi - sizeof(Q931_info_t);
00146 p[0] = IE_BEARER;
00147 p[1] = l;
00148 p[2] = 0x80 + (coding<<5) + capability;
00149 p[3] = 0x80 + (mode<<5) + rate;
00150 if (multi >= 0)
00151 p[4] = 0x80 + multi;
00152 if (user >= 0)
00153 p[4+(multi>=0)] = 0xa0 + user;
00154 }
00155
00156 static void dec_ie_bearer(unsigned char *p, Q931_info_t *qi, int *coding, int *capability, int *mode, int *rate, int *multi, int *user,
00157 int *async, int *urate, int *stopbits, int *dbits, int *parity, int nt, struct misdn_bchannel *bc)
00158 {
00159 int octet;
00160 *coding = -1;
00161 *capability = -1;
00162 *mode = -1;
00163 *rate = -1;
00164 *multi = -1;
00165 *user = -1;
00166 *async = -1;
00167 *urate = -1;
00168 *stopbits = -1;
00169 *dbits = -1;
00170 *parity = -1;
00171
00172 if (!nt)
00173 {
00174 p = NULL;
00175 #ifdef LLC_SUPPORT
00176 if (qi->QI_ELEMENT(llc)) {
00177
00178 p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(llc) + 1;
00179 }
00180 #endif
00181 if (qi->QI_ELEMENT(bearer_capability))
00182 p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(bearer_capability) + 1;
00183 }
00184 if (!p)
00185 return;
00186
00187 if (p[0] < 2)
00188 {
00189 printf("%s: ERROR: IE too short (%d).\n", __FUNCTION__, p[0]);
00190 return;
00191 }
00192
00193 *coding = (p[1]&0x60) >> 5;
00194 *capability = p[1] & 0x1f;
00195 octet = 2;
00196 if (!(p[1] & 0x80))
00197 octet++;
00198
00199 if (p[0] < octet)
00200 goto done;
00201
00202 *mode = (p[octet]&0x60) >> 5;
00203 *rate = p[octet] & 0x1f;
00204
00205 octet++;
00206
00207 if (p[0] < octet)
00208 goto done;
00209
00210 if (*rate == 0x18) {
00211
00212 *multi = p[octet++] & 0x7f;
00213 }
00214
00215 if (p[0] < octet)
00216 goto done;
00217
00218
00219 if ((p[octet] & 0x60) == 0x20) {
00220 *user = p[octet] & 0x1f;
00221
00222 if (p[0] <= octet)
00223 goto done;
00224
00225 if (p[octet++] & 0x80)
00226 goto l2;
00227
00228 *async = !!(p[octet] & 0x40);
00229
00230 *urate = p[octet] & 0x1f;
00231
00232 if (p[0] <= octet)
00233 goto done;
00234
00235 if (p[octet++] & 0x80)
00236 goto l2;
00237
00238
00239
00240 if (p[0] <= octet)
00241 goto done;
00242
00243 if (p[octet++] & 0x80)
00244 goto l2;
00245
00246
00247
00248 if (p[0] <= octet)
00249 goto done;
00250
00251 if (!p[octet++] & 0x80)
00252 goto l2;
00253
00254
00255
00256 *stopbits = (p[octet] & 0x60) >> 5;
00257 *dbits = (p[octet] & 0x18) >> 3;
00258 *parity = p[octet] & 7;
00259
00260 octet++;
00261 }
00262 l2:
00263 done:
00264 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);
00265 }
00266
00267
00268
00269 #if 0
00270 static void enc_ie_call_id(unsigned char **ntmode, msg_t *msg, char *callid, int callid_len, int nt, struct misdn_bchannel *bc)
00271 {
00272 unsigned char *p;
00273 Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
00274 int l;
00275
00276 char debug[25];
00277 int i;
00278
00279 if (!callid || callid_len<=0)
00280 {
00281 return;
00282 }
00283 if (callid_len>8)
00284 {
00285 printf("%s: ERROR: callid_len(%d) is out of range.\n", __FUNCTION__, callid_len);
00286 return;
00287 }
00288
00289 i = 0;
00290 while(i < callid_len)
00291 {
00292 if (MISDN_IE_DEBG) printf(debug+(i*3), " %02x", callid[i]);
00293 i++;
00294 }
00295
00296 if (MISDN_IE_DEBG) printf(" callid%s\n", debug);
00297
00298 l = callid_len;
00299 p = msg_put(msg, l+2);
00300 if (nt)
00301 *ntmode = p+1;
00302 else
00303 qi->QI_ELEMENT(call_id) = p - (unsigned char *)qi - sizeof(Q931_info_t);
00304 p[0] = IE_CALL_ID;
00305 p[1] = l;
00306 memcpy(p+2, callid, callid_len);
00307 }
00308 #endif
00309
00310 #if 0
00311 static void dec_ie_call_id(unsigned char *p, Q931_info_t *qi, char *callid, int *callid_len, int nt, struct misdn_bchannel *bc)
00312 {
00313 char debug[25];
00314 int i;
00315
00316 *callid_len = -1;
00317
00318 if (!nt)
00319 {
00320 p = NULL;
00321 if (qi->QI_ELEMENT(call_id))
00322 p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(call_id) + 1;
00323 }
00324 if (!p)
00325 return;
00326 if (p[0] > 8)
00327 {
00328 printf("%s: ERROR: IE too long (%d).\n", __FUNCTION__, p[0]);
00329 return;
00330 }
00331
00332 *callid_len = p[0];
00333 memcpy(callid, p+1, *callid_len);
00334
00335 i = 0;
00336 while(i < *callid_len)
00337 {
00338 if (MISDN_IE_DEBG) printf(debug+(i*3), " %02x", callid[i]);
00339 i++;
00340 }
00341
00342 if (MISDN_IE_DEBG) printf(" callid%s\n", debug);
00343 }
00344 #endif
00345
00346
00347 static void enc_ie_called_pn(unsigned char **ntmode, msg_t *msg, int type, int plan, char *number, int nt, struct misdn_bchannel *bc)
00348 {
00349 unsigned char *p;
00350 Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
00351 int l;
00352
00353 if (type<0 || type>7)
00354 {
00355 printf("%s: ERROR: type(%d) is out of range.\n", __FUNCTION__, type);
00356 return;
00357 }
00358 if (plan<0 || plan>15)
00359 {
00360 printf("%s: ERROR: plan(%d) is out of range.\n", __FUNCTION__, plan);
00361 return;
00362 }
00363 if (!number[0])
00364 {
00365 printf("%s: ERROR: number is not given.\n", __FUNCTION__);
00366 return;
00367 }
00368
00369 if (MISDN_IE_DEBG) printf(" type=%d plan=%d number='%s'\n", type, plan, number);
00370
00371 l = 1+strlen((char *)number);
00372 p = msg_put(msg, l+2);
00373 if (nt)
00374 *ntmode = p+1;
00375 else
00376 qi->QI_ELEMENT(called_nr) = p - (unsigned char *)qi - sizeof(Q931_info_t);
00377 p[0] = IE_CALLED_PN;
00378 p[1] = l;
00379 p[2] = 0x80 + (type<<4) + plan;
00380 strncpy((char *)p+3, (char *)number, strlen((char *)number));
00381 }
00382
00383 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)
00384 {
00385 *type = -1;
00386 *plan = -1;
00387 *number = '\0';
00388
00389 if (!nt)
00390 {
00391 p = NULL;
00392 if (qi->QI_ELEMENT(called_nr))
00393 p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(called_nr) + 1;
00394 }
00395 if (!p)
00396 return;
00397 if (p[0] < 2)
00398 {
00399 printf("%s: ERROR: IE too short (%d).\n", __FUNCTION__, p[0]);
00400 return;
00401 }
00402
00403 *type = (p[1]&0x70) >> 4;
00404 *plan = p[1] & 0xf;
00405 strnncpy(number, (char *)p+2, p[0]-1, number_len);
00406
00407 if (MISDN_IE_DEBG) printf(" type=%d plan=%d number='%s'\n", *type, *plan, number);
00408 }
00409
00410
00411
00412 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)
00413 {
00414 unsigned char *p;
00415 Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
00416 int l;
00417
00418 if (type<0 || type>7)
00419 {
00420 printf("%s: ERROR: type(%d) is out of range.\n", __FUNCTION__, type);
00421 return;
00422 }
00423 if (plan<0 || plan>15)
00424 {
00425 printf("%s: ERROR: plan(%d) is out of range.\n", __FUNCTION__, plan);
00426 return;
00427 }
00428 if (present>3)
00429 {
00430 printf("%s: ERROR: present(%d) is out of range.\n", __FUNCTION__, present);
00431 return;
00432 }
00433 if (present >= 0) if (screen<0 || screen>3)
00434 {
00435 printf("%s: ERROR: screen(%d) is out of range.\n", __FUNCTION__, screen);
00436 return;
00437 }
00438
00439 if (MISDN_IE_DEBG) printf(" type=%d plan=%d present=%d screen=%d number='%s'\n", type, plan, present, screen, number);
00440
00441 l = 1;
00442 if (number) if (number[0])
00443 l += strlen((char *)number);
00444 if (present >= 0)
00445 l += 1;
00446 p = msg_put(msg, l+2);
00447 if (nt)
00448 *ntmode = p+1;
00449 else
00450 qi->QI_ELEMENT(calling_nr) = p - (unsigned char *)qi - sizeof(Q931_info_t);
00451 p[0] = IE_CALLING_PN;
00452 p[1] = l;
00453 if (present >= 0)
00454 {
00455 p[2] = 0x00 + (type<<4) + plan;
00456 p[3] = 0x80 + (present<<5) + screen;
00457 if (number) if (number[0])
00458 strncpy((char *)p+4, (char *)number, strlen((char *)number));
00459 } else
00460 {
00461 p[2] = 0x80 + (type<<4) + plan;
00462 if (number) if (number[0])
00463 strncpy((char *)p+3, (char *)number, strlen((char *)number));
00464 }
00465 }
00466
00467 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)
00468 {
00469 *type = -1;
00470 *plan = -1;
00471 *present = -1;
00472 *screen = -1;
00473 *number = '\0';
00474
00475 if (!nt)
00476 {
00477 p = NULL;
00478 if (qi->QI_ELEMENT(calling_nr))
00479 p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(calling_nr) + 1;
00480 }
00481 if (!p)
00482 return;
00483 if (p[0] < 1)
00484 {
00485 printf("%s: ERROR: IE too short (%d).\n", __FUNCTION__, p[0]);
00486 return;
00487 }
00488
00489 *type = (p[1]&0x70) >> 4;
00490 *plan = p[1] & 0xf;
00491 if (!(p[1] & 0x80))
00492 {
00493 if (p[0] < 2)
00494 {
00495 printf("%s: ERROR: IE too short (%d).\n", __FUNCTION__, p[0]);
00496 return;
00497 }
00498 *present = (p[2]&0x60) >> 5;
00499 *screen = p[2] & 0x3;
00500 strnncpy(number, (char *)p+3, p[0]-2, number_len);
00501 } else
00502 {
00503 strnncpy(number, (char *)p+2, p[0]-1, number_len);
00504
00505
00506
00507 }
00508
00509 if (MISDN_IE_DEBG) printf(" type=%d plan=%d present=%d screen=%d number='%s'\n", *type, *plan, *present, *screen, number);
00510 }
00511
00512
00513
00514 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)
00515 {
00516 unsigned char *p;
00517 Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
00518 int l;
00519
00520 if (type<0 || type>7)
00521 {
00522 printf("%s: ERROR: type(%d) is out of range.\n", __FUNCTION__, type);
00523 return;
00524 }
00525 if (plan<0 || plan>15)
00526 {
00527 printf("%s: ERROR: plan(%d) is out of range.\n", __FUNCTION__, plan);
00528 return;
00529 }
00530 if (present>3)
00531 {
00532 printf("%s: ERROR: present(%d) is out of range.\n", __FUNCTION__, present);
00533 return;
00534 }
00535 if (present >= 0) if (screen<0 || screen>3)
00536 {
00537 printf("%s: ERROR: screen(%d) is out of range.\n", __FUNCTION__, screen);
00538 return;
00539 }
00540
00541 if (MISDN_IE_DEBG) printf(" type=%d plan=%d present=%d screen=%d number='%s'\n", type, plan, present, screen, number);
00542
00543 l = 1;
00544 if (number) if (number[0])
00545 l += strlen((char *)number);
00546 if (present >= 0)
00547 l += 1;
00548 p = msg_put(msg, l+2);
00549 if (nt)
00550 *ntmode = p+1;
00551 else
00552 qi->QI_ELEMENT(connected_nr) = p - (unsigned char *)qi - sizeof(Q931_info_t);
00553 p[0] = IE_CONNECT_PN;
00554 p[1] = l;
00555 if (present >= 0)
00556 {
00557 p[2] = 0x00 + (type<<4) + plan;
00558 p[3] = 0x80 + (present<<5) + screen;
00559 if (number) if (number[0])
00560 strncpy((char *)p+4, (char *)number, strlen((char *)number));
00561 } else
00562 {
00563 p[2] = 0x80 + (type<<4) + plan;
00564 if (number) if (number[0])
00565 strncpy((char *)p+3, (char *)number, strlen((char *)number));
00566 }
00567 }
00568
00569 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)
00570 {
00571 *type = -1;
00572 *plan = -1;
00573 *present = -1;
00574 *screen = -1;
00575 *number = '\0';
00576
00577 if (!nt)
00578 {
00579 p = NULL;
00580 if (qi->QI_ELEMENT(connected_nr))
00581 p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(connected_nr) + 1;
00582 }
00583 if (!p)
00584 return;
00585 if (p[0] < 1)
00586 {
00587 printf("%s: ERROR: IE too short (%d).\n", __FUNCTION__, p[0]);
00588 return;
00589 }
00590
00591 *type = (p[1]&0x70) >> 4;
00592 *plan = p[1] & 0xf;
00593 if (!(p[1] & 0x80))
00594 {
00595 if (p[0] < 2)
00596 {
00597 printf("%s: ERROR: IE too short (%d).\n", __FUNCTION__, p[0]);
00598 return;
00599 }
00600 *present = (p[2]&0x60) >> 5;
00601 *screen = p[2] & 0x3;
00602 strnncpy(number, (char *)p+3, p[0]-2, number_len);
00603 } else
00604 {
00605 strnncpy(number, (char *)p+2, p[0]-1, number_len);
00606 }
00607
00608 if (MISDN_IE_DEBG) printf(" type=%d plan=%d present=%d screen=%d number='%s'\n", *type, *plan, *present, *screen, number);
00609 }
00610
00611
00612
00613 static void enc_ie_cause(unsigned char **ntmode, msg_t *msg, int location, int cause, int nt, struct misdn_bchannel *bc)
00614 {
00615 unsigned char *p;
00616 Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
00617 int l;
00618
00619 if (location<0 || location>7)
00620 {
00621 printf("%s: ERROR: location(%d) is out of range.\n", __FUNCTION__, location);
00622 return;
00623 }
00624 if (cause<0 || cause>127)
00625 {
00626 printf("%s: ERROR: cause(%d) is out of range.\n", __FUNCTION__, cause);
00627 return;
00628 }
00629
00630 if (MISDN_IE_DEBG) printf(" location=%d cause=%d\n", location, cause);
00631
00632 l = 2;
00633 p = msg_put(msg, l+2);
00634 if (nt)
00635 *ntmode = p+1;
00636 else
00637 qi->QI_ELEMENT(cause) = p - (unsigned char *)qi - sizeof(Q931_info_t);
00638 p[0] = IE_CAUSE;
00639 p[1] = l;
00640 p[2] = 0x80 + location;
00641 p[3] = 0x80 + cause;
00642 }
00643
00644 #if 0
00645 static void enc_ie_cause_standalone(unsigned char **ntmode, msg_t *msg, int location, int cause, int nt, struct misdn_bchannel *bc)
00646 {
00647 unsigned char *p = msg_put(msg, 4);
00648 Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
00649 if (ntmode)
00650 *ntmode = p+1;
00651 else
00652 qi->QI_ELEMENT(cause) = p - (unsigned char *)qi - sizeof(Q931_info_t);
00653 p[0] = IE_CAUSE;
00654 p[1] = 2;
00655 p[2] = 0x80 + location;
00656 p[3] = 0x80 + cause;
00657 }
00658 #endif
00659
00660 static void dec_ie_cause(unsigned char *p, Q931_info_t *qi, int *location, int *cause, int nt, struct misdn_bchannel *bc)
00661 {
00662 *location = -1;
00663 *cause = -1;
00664
00665 if (!nt)
00666 {
00667 p = NULL;
00668 if (qi->QI_ELEMENT(cause))
00669 p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(cause) + 1;
00670 }
00671 if (!p)
00672 return;
00673 if (p[0] < 2)
00674 {
00675 printf("%s: ERROR: IE too short (%d).\n", __FUNCTION__, p[0]);
00676 return;
00677 }
00678
00679 *location = p[1] & 0x0f;
00680 *cause = p[2] & 0x7f;
00681
00682 if (MISDN_IE_DEBG) printf(" location=%d cause=%d\n", *location, *cause);
00683 }
00684
00685
00686
00687 static void enc_ie_channel_id(unsigned char **ntmode, msg_t *msg, int exclusive, int channel, int nt, struct misdn_bchannel *bc)
00688 {
00689 unsigned char *p;
00690 Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
00691 int l;
00692 struct misdn_stack *stack=get_stack_by_bc(bc);
00693 int pri = stack->pri;
00694
00695 if (exclusive<0 || exclusive>1)
00696 {
00697 printf("%s: ERROR: exclusive(%d) is out of range.\n", __FUNCTION__, exclusive);
00698 return;
00699 }
00700 if ((channel<0 || channel>0xff)
00701 || (!pri && (channel>2 && channel<0xff))
00702 || (pri && (channel>31 && channel<0xff))
00703 || (pri && channel==16))
00704 {
00705 printf("%s: ERROR: channel(%d) is out of range.\n", __FUNCTION__, channel);
00706 return;
00707 }
00708
00709
00710
00711
00712 if (!pri)
00713 {
00714
00715 l = 1;
00716 p = msg_put(msg, l+2);
00717 if (nt)
00718 *ntmode = p+1;
00719 else
00720 qi->QI_ELEMENT(channel_id) = p - (unsigned char *)qi - sizeof(Q931_info_t);
00721 p[0] = IE_CHANNEL_ID;
00722 p[1] = l;
00723 if (channel == 0xff)
00724 channel = 3;
00725 p[2] = 0x80 + (exclusive<<3) + channel;
00726
00727 } else
00728 {
00729
00730 if (channel == 0)
00731 return;
00732
00733 if (channel == 0xff)
00734 {
00735 l = 1;
00736 p = msg_put(msg, l+2);
00737 if (nt)
00738 *ntmode = p+1;
00739 else
00740 qi->QI_ELEMENT(channel_id) = p - (unsigned char *)qi - sizeof(Q931_info_t);
00741 p[0] = IE_CHANNEL_ID;
00742 p[1] = l;
00743 p[2] = 0x80 + 0x20 + 0x03;
00744
00745 return;
00746 }
00747 l = 3;
00748 p = msg_put(msg, l+2);
00749 if (nt)
00750 *ntmode = p+1;
00751 else
00752 qi->QI_ELEMENT(channel_id) = p - (unsigned char *)qi - sizeof(Q931_info_t);
00753 p[0] = IE_CHANNEL_ID;
00754 p[1] = l;
00755 p[2] = 0x80 + 0x20 + (exclusive<<3) + 0x01;
00756 p[3] = 0x80 + 3;
00757 p[4] = 0x80 + channel;
00758
00759 }
00760 }
00761
00762 static void dec_ie_channel_id(unsigned char *p, Q931_info_t *qi, int *exclusive, int *channel, int nt, struct misdn_bchannel *bc)
00763 {
00764 struct misdn_stack *stack=get_stack_by_bc(bc);
00765 int pri =stack->pri;
00766
00767 *exclusive = -1;
00768 *channel = -1;
00769
00770 if (!nt)
00771 {
00772 p = NULL;
00773 if (qi->QI_ELEMENT(channel_id))
00774 p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(channel_id) + 1;
00775 }
00776 if (!p)
00777 return;
00778 if (p[0] < 1)
00779 {
00780 printf("%s: ERROR: IE too short (%d).\n", __FUNCTION__, p[0]);
00781 return;
00782 }
00783
00784 if (p[1] & 0x40)
00785 {
00786 printf("%s: ERROR: refering to channels of other interfaces is not supported.\n", __FUNCTION__);
00787 return;
00788 }
00789 if (p[1] & 0x04)
00790 {
00791 printf("%s: ERROR: using d-channel is not supported.\n", __FUNCTION__);
00792 return;
00793 }
00794
00795 *exclusive = (p[1]&0x08) >> 3;
00796 if (!pri)
00797 {
00798
00799 if (p[1] & 0x20)
00800 {
00801 printf("%s: ERROR: extended channel ID with non PRI interface.\n", __FUNCTION__);
00802 return;
00803 }
00804 *channel = p[1] & 0x03;
00805 if (*channel == 3)
00806 *channel = 0xff;
00807 } else
00808 {
00809
00810 if (p[0] < 1)
00811 {
00812 printf("%s: ERROR: IE too short for PRI (%d).\n", __FUNCTION__, p[0]);
00813 return;
00814 }
00815 if (!(p[1] & 0x20))
00816 {
00817 printf("%s: ERROR: basic channel ID with PRI interface.\n", __FUNCTION__);
00818 return;
00819 }
00820 if ((p[1]&0x03) == 0x00)
00821 {
00822
00823 *channel = 0;
00824 return;
00825 }
00826 if ((p[1]&0x03) == 0x03)
00827 {
00828
00829 *channel = 0xff;
00830 return;
00831 }
00832 if (p[0] < 3)
00833 {
00834 printf("%s: ERROR: IE too short for PRI with channel(%d).\n", __FUNCTION__, p[0]);
00835 return;
00836 }
00837 if (p[2] & 0x10)
00838 {
00839 printf("%s: ERROR: channel map not supported.\n", __FUNCTION__);
00840 return;
00841 }
00842 *channel = p[3] & 0x7f;
00843 if ( (*channel<1) | (*channel==16) | (*channel>31))
00844 {
00845 printf("%s: ERROR: PRI interface channel out of range (%d).\n", __FUNCTION__, *channel);
00846 return;
00847 }
00848
00849 }
00850
00851 if (MISDN_IE_DEBG) printf(" exclusive=%d channel=%d\n", *exclusive, *channel);
00852 }
00853
00854
00855
00856 static void enc_ie_date(unsigned char **ntmode, msg_t *msg, time_t ti, int nt, struct misdn_bchannel *bc)
00857 {
00858 unsigned char *p;
00859 Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
00860 int l;
00861 struct timeval tv = { ti, 0 };
00862 struct ast_tm tm;
00863
00864 ast_localtime(&tv, &tm, NULL);
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) sprintf(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) sprintf(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