/* * Function: MatchDialTemplate() * * Parameters: pattern - pattern string to match * line - line number to match * (May be 0 to match all lines) * timeout - returned dial timeout in seconds * (May be NULL to not get a timeout) * rewrite - buffer to hold rewritten string * (May be NULL for no rewrite) * rewritelen - Bytes available in the buffer to write to * routemode - pointer to location to hold route mode returned * (May be NULL to not get a routemode) * tone - pointer to location to hold tone returned * * Description: Find the best template to match a pattern * * Returns: DialMatchAction */ DialMatchAction MatchDialTemplate (const char *pattern, const line_t line, int *timeout, char *rewrite, int rewritelen, RouteMode *pRouteMode, vcm_tones_t *pTone) { DialMatchAction result = DIAL_NOMATCH; struct DialTemplate *ptempl = basetemplate; struct DialTemplate *pbestmatch = NULL; boolean bestmatch_dialnow = FALSE; int best_comma_count = 0; DialMatchAction partialmatch_type = DIAL_NOMATCH; boolean partialmatch = FALSE; int matchlen = 0; int partialmatchlen = 0; int givedialtone = 0; int comma_counter = 0; /* * We need to provide a default rewrite string in case we do not have any template matches. * This happens when there is no template match (such as no * pattern) and when they have * no dial plan file at all */ if (rewrite != NULL) { char *output = rewrite; int room = rewritelen; addbytes(&output, &room, pattern, -1); } /* * If the dialplan is empty, check to see if a # is in the pattern * and return DIAL_IMMEDIATELY. If not go ahead and return * DIAL_NOMATCH since there will be no template match in * an empty dialplan. */ if (ptempl == NULL) { if (strchr(pattern, '#') && (poundDialingEnabled())) { return DIAL_IMMEDIATELY; } else { return DIAL_NOMATCH; } } /* * Iterate through all the templates. Skip the this template if it's not * for this line or all lines. */ while (ptempl != NULL) { if (MatchLineNumber(ptempl->line, line)) { char *pinput = (char *) pattern; char *pmatch = ptempl->pattern; int thismatchlen = 0; DialMatchAction thismatch = DIAL_FULLMATCH; char *subs[MAX_SUBTITUTIONS]; int subslen[MAX_SUBTITUTIONS]; int subscount = -1; boolean dialnow = FALSE; while (*pinput) { int idx; /* Since the code below combines multiple , * in a row into "one" , only increment * comma counter once instead of once * for each comma combined. */ if (pmatch[0] == ',') { comma_counter++; } /* * Skip over any dial tone characters */ while (pmatch[0] == ',') { pmatch++; } /* * If this is a pattern character, we need to capture the digits for the * substitution strings */ if (((pmatch[0] == '.') && isDialedDigit(pinput[0])) || (pmatch[0] == '*')) { /* * Get the next index in the substitution array (if any) * Note that if they have more pattern sections in the pattern string * the last one will get the counts for the characters. So for example * with the MAX_SUBSTITUTIONS of 5 and a pattern of * 1.2.3.4.5.6.7. * and an input string of * 1a2b3c4d5e6f7g * the arrays of substitions would come out as follows: * %0 = 1a2b3c4d5e6f7g (as expected) * %1 = a (as expected) * %2 = b (as expected) * %3 = c (as expected) * %4 = d (as expected) * %5 = e6f NOT what they really wanted, but predictable from the algorithm */ if (subscount < (MAX_SUBTITUTIONS - 1)) { subscount++; subs[subscount] = pinput; subslen[subscount] = 1; } if (pmatch[0] == '.') { thismatch = DIAL_FULLPATTERN; /* * . in the pattern will match anything but doesn't contribute * to our matching length for finding the best template */ while (isdigit(pinput[1]) && (pmatch[1] == '.')) { pinput++; pmatch++; subslen[subscount]++; } } else { thismatch = DIAL_WILDPATTERN; /* * '*' is a wild card to match 1 or more characters * Do a hungry first match * * Note: If match is currently pointing to an escape character, * we need to go past it to match the actual character. */ if (pmatch[1] == DIAL_ESCAPE) { idx = 2; } else { idx = 1; } /* * The '*' will not match the '#' character since its' default use * causes the phone to "dial immediately" */ if ((pinput[0] == '#') && (poundDialingEnabled())) { dialnow = TRUE; } else { while ((pinput[1] != '\0') && (pinput[1] != pmatch[idx])) { /* * If '#' is found and pound dialing is enabled, break out of the loop. */ if ((pinput[1] == '#') && (poundDialingEnabled())) { break; } pinput++; subslen[subscount]++; } } } /* * Any other character must match exactly */ } else { /* * Look for the Escape character '\' and remove it * Right now, the only character that needs to be escaped is '*' * Note that we treat \ at the end of a line as a non-special * character */ if ((pmatch[0] == DIAL_ESCAPE) && (pmatch[1] != '\0')) { pmatch++; } if (pmatch[0] != pinput[0]) { /* * We found a '#' that doesn't match the current match template * This means that the '#" should be interpreted as the dial * termination character. */ if ((pinput[0] == '#') && (poundDialingEnabled())) { dialnow = TRUE; break; } /* * No match, so abandon with no pattern to select */ thismatchlen = -1; thismatch = DIAL_NOMATCH; break; } else { /* * We matched one character, count it for the overall template match */ thismatchlen++; } } pmatch++; pinput++; } /* * *pinput = NULL means we matched everything that * was dialed in this template * Partial never matches * rules * Since 97. should have precendence over 9.. * also check matchlen. * Since fullmatches (exact digits) have precendence * over fullpattern (.) check matchtype */ if ((*pinput == NUL) || (dialnow)) { if ((thismatchlen > partialmatchlen) || ((thismatchlen == partialmatchlen) && (thismatch > partialmatch_type))) { partialmatch_type = thismatch; partialmatchlen = thismatchlen; pbestmatch = ptempl; partialmatch = TRUE; bestmatch_dialnow = dialnow; best_comma_count = comma_counter; result = DIAL_NOMATCH; } } /* * If we exhausted the match string, then the template is a perfect match * However, we don't want to take this as the best template unless it matched * more digits than any other pattern. For example if we have a pattern of * 9011* * 9.11 * We would want 9011 to match against the first one even though it is not complete * * We also have to be careful that a pattern such as * * * does not beat something like * 9....... * when you have 94694210 */ if (pmatch[0] == '\0') { /* * If this pattern is better, we want to adopt it */ if ((thismatchlen > matchlen) || ((thismatchlen == matchlen) && (thismatch > result)) || ((thismatch == DIAL_WILDPATTERN) && ((result == DIAL_NOMATCH) && (partialmatch == FALSE)))) { /* * this is a better match than what we found before */ pbestmatch = ptempl; bestmatch_dialnow = dialnow; matchlen = thismatchlen; result = thismatch; /* * Generate a rewrite string * * <TEMPLATE MATCH="31." Timeout="0" User="******" Rewrite="11111111%s"/> * 310 -> 111111110 * <TEMPLATE MATCH="32.." Timeout="0" User="******" Rewrite="122222232.."/> * 3255 -> 12222223255 * <TEMPLATE MATCH="33..." Timeout="0" User="******" Rewrite="13333333%1"/> * <TEMPLATE MATCH="34..1.." Timeout="0" User="******" Rewrite="14444%155%2"/> * <TEMPLATE MATCH="34..2.." Timeout="0" User="******" Rewrite="1444%s"/> * <TEMPLATE MATCH="34..3.." Timeout="0" User="******" Rewrite="11..11.."/> */ if (rewrite != NULL) { int dotindex = -1; int dotsleft = 0; char *output = rewrite; int room = rewritelen; char *prewrite = pbestmatch->rewrite; if ((prewrite == NULL) || (prewrite[0] == '\0')) { /* * Null or empty patterns produce the input as the result */ addbytes(&output, &room, pattern, -1); } else { while (prewrite[0] != '\0') { if (prewrite[0] == '.') { /* * For a dot, we copy over the single previously matched character */ while ((dotsleft == 0) && (dotindex < subscount)) { dotindex++; dotsleft = subslen[dotindex]; } if (dotsleft > 0) { addbytes(&output, &room, subs[dotindex] + subslen[dotindex] - dotsleft, 1); dotsleft--; } } else if (prewrite[0] == '%') { int idx = prewrite[1] - '1'; prewrite++; // Consume the % if ((prewrite[0] == 's') || (prewrite[0] == '0')) { /* * %0 or %s means copy the entire input string */ addbytes(&output, &room, pattern, -1); } else if ((idx >= 0) && (idx <= subscount)) { /* * %n where n is withing the range of substitution patterns copies over * all of the characters that matched that group */ addbytes(&output, &room, subs[idx], subslen[idx]); } else if (prewrite[0]) { /* * %anything copies over anything. This is how you would get a * % in the rewrite string */ addbytes(&output, &room, prewrite, 1); } } else { /* * Just a normal character, just copy it over */ addbytes(&output, &room, prewrite, 1); } /* * Consume the character we used (if any) */ if (prewrite[0]) { prewrite++; } } } /* * Put on the usermode (if specified) */ switch (pbestmatch->userMode) { case UserPhone: if (*(output - 1) == '>') { --room; --output; addbytes(&output, &room, ";user=phone>", -1); } else { addbytes(&output, &room, ";user=phone", -1); } break; case UserIP: if (*(output - 1) == '>') { --room; --output; addbytes(&output, &room, ";user=ip>", -1); } else { addbytes(&output, &room, ";user=ip", -1); } break; default: break; } } } } else if (pmatch[0] == ',') { givedialtone = 1; } /* * Even if this pattern was not taken as a full match, remember the longest length */ if (thismatchlen > matchlen) { matchlen = thismatchlen; } } /* * Try the next template */ ptempl = ptempl->next; comma_counter = 0; } /* * Did we get any templates at all? */ switch (result) { case DIAL_FULLPATTERN: case DIAL_FULLMATCH: givedialtone = 0; /* FALLTHROUGH */ case DIAL_WILDPATTERN: if (timeout != NULL) { *timeout = pbestmatch->timeout; } if (pRouteMode != NULL) { *pRouteMode = pbestmatch->routeMode; } break; default: /* * If we have received a partial match, set the timeout * to be the default timeout (i.e. interdigit timeout) * to allow for additional digit collection. */ if (partialmatch) { if ((timeout != NULL) && (*timeout == 0)) { *timeout = DIAL_TIMEOUT; } } else if ((*(pattern + strlen(pattern) - 1) == '#') && (poundDialingEnabled())) { /* * No template was matched, however if the dialplan * does not have the default '*' rule and the pattern * dialed did not match any other template this code * would be hit. Therefore check for a # to see if * we need to set the dial immediately flag. */ result = DIAL_IMMEDIATELY; } break; } /* * If the bestmatch template says to dialnow, do it. */ if (bestmatch_dialnow) { /* * If there is partial match, and dialled pattern has "#", * then do not Dial immediately. Give user a chance to edit * the mistake if any. */ if (!((poundDialingEnabled()) && (strchr(pattern, '#')) && partialmatch)) { result = DIAL_IMMEDIATELY; if (timeout != NULL) { *timeout = 0; } } } if (givedialtone) { /* * Give user dial-tone. The tone given * is based on the rule. Default tone * is Outside-Dial-Tone. */ if (pTone != NULL) { *pTone = VCM_DEFAULT_TONE; if (pbestmatch != NULL) { if (best_comma_count < pbestmatch->tones_defined) { *pTone = pbestmatch->tone[best_comma_count]; } } } result = DIAL_GIVETONE; } return result; // Nothing special to match against }
int bootpass(Boot *b, void *vbuf, int nbuf) { char *buf, *ebuf; Hdr *hdr; ulong magic, entry, data, text, bss; uvlong entry64; if(b->state == FAILED) return FAIL; if(nbuf == 0) goto Endofinput; buf = vbuf; ebuf = buf+nbuf; while(addbytes(&b->wp, b->ep, &buf, ebuf) == 0) { switch(b->state) { case INITKERNEL: b->state = READEXEC; b->bp = (char*)&b->hdr; b->wp = b->bp; b->ep = b->bp+sizeof(Hdr); break; case READEXEC: hdr = &b->hdr; magic = GLLONG(hdr->magic); if(magic == I_MAGIC || magic == S_MAGIC) { b->state = READ9TEXT; b->bp = (char*)PADDR(GLLONG(hdr->entry)); b->wp = b->bp; b->ep = b->wp+GLLONG(hdr->text); if(magic == I_MAGIC){ memmove(b->bp, b->hdr.uvl, sizeof(b->hdr.uvl)); b->wp += sizeof(b->hdr.uvl); } print("%lud", GLLONG(hdr->text)); break; } /* check for gzipped kernel */ if(b->bp[0] == 0x1F && (uchar)b->bp[1] == 0x8B && b->bp[2] == 0x08) { b->state = READGZIP; b->bp = (char*)malloc(1440*1024); b->wp = b->bp; b->ep = b->wp + 1440*1024; memmove(b->bp, &b->hdr, sizeof(Hdr)); b->wp += sizeof(Hdr); print("gz..."); break; } /* * Check for ELF. */ if(memcmp(b->bp, elfident, 4) == 0){ b->state = READEHDR; b->bp = (char*)&ehdr; b->wp = b->bp; b->ep = b->wp + sizeof(Ehdr); memmove(b->bp, &b->hdr, sizeof(Hdr)); b->wp += sizeof(Hdr); print("elf..."); break; } print("bad kernel format (magic == %#lux)\n", magic); b->state = FAILED; return FAIL; case READ9TEXT: hdr = &b->hdr; b->state = READ9DATA; b->bp = (char*)PGROUND(PADDR(GLLONG(hdr->entry))+GLLONG(hdr->text)); b->wp = b->bp; b->ep = b->wp + GLLONG(hdr->data); print("+%ld", GLLONG(hdr->data)); break; case READ9DATA: hdr = &b->hdr; bss = GLLONG(hdr->bss); memset(b->ep, 0, bss); print("+%ld=%ld\n", bss, GLLONG(hdr->text)+GLLONG(hdr->data)+bss); b->state = TRYBOOT; return ENOUGH; case READEHDR: if(!readehdr(b)){ print("readehdr failed\n"); b->state = FAILED; return FAIL; } break; case READPHDR: if(!readphdr(b)){ b->state = FAILED; return FAIL; } break; case READEPAD: if(!readepad(b)){ b->state = FAILED; return FAIL; } break; case READEDATA: if(!readedata(b)){ b->state = FAILED; return FAIL; } if(b->state == TRYBOOT) return ENOUGH; break; case TRYBOOT: case TRYEBOOT: case READGZIP: return ENOUGH; case READ9LOAD: case INIT9LOAD: panic("9load"); default: panic("bootstate"); } } return MORE; Endofinput: /* end of input */ switch(b->state) { case INITKERNEL: case READEXEC: case READ9TEXT: case READ9DATA: case READEHDR: case READPHDR: case READEPAD: case READEDATA: print("premature EOF\n"); b->state = FAILED; return FAIL; case TRYBOOT: entry = GLLONG(b->hdr.entry); magic = GLLONG(b->hdr.magic); if(magic == I_MAGIC){ print("entry: 0x%lux\n", entry); warp9(PADDR(entry)); } else if(magic == S_MAGIC){ entry64 = beswav(b->hdr.uvl[0]); warp64(entry64); } b->state = FAILED; return FAIL; case TRYEBOOT: entry = GLLONG(b->hdr.entry); if(ehdr.machine == I386){ print("entry: 0x%lux\n", entry); warp9(PADDR(entry)); } else if(ehdr.machine == AMD64){ print("entry: 0x%lux\n", entry); warp64(entry); } b->state = FAILED; return FAIL; case READGZIP: hdr = &b->hdr; if(b->bp[0] != 0x1F || (uchar)b->bp[1] != 0x8B || b->bp[2] != 0x08) print("lost magic\n"); print("%ld => ", b->wp - b->bp); if(gunzip((uchar*)hdr, sizeof(*hdr), (uchar*)b->bp, b->wp - b->bp) < sizeof(*hdr)) { print("badly compressed kernel\n"); return FAIL; } entry = GLLONG(hdr->entry); text = GLLONG(hdr->text); data = GLLONG(hdr->data); bss = GLLONG(hdr->bss); print("%lud+%lud+%lud=%lud\n", text, data, bss, text+data+bss); if(gunzip((uchar*)PADDR(entry)-sizeof(Exec), sizeof(Exec)+text+data, (uchar*)b->bp, b->wp-b->bp) < sizeof(Exec)+text+data) { print("error uncompressing kernel\n"); return FAIL; } /* relocate data to start at page boundary */ memmove((void*)PGROUND(PADDR(entry+text)), (void*)(PADDR(entry+text)), data); entry = GLLONG(b->hdr.entry); magic = GLLONG(b->hdr.magic); if(magic == I_MAGIC){ print("entry: 0x%lux\n", entry); warp9(PADDR(entry)); } else if(magic == S_MAGIC){ entry64 = beswav(b->hdr.uvl[0]); warp64(entry64); } b->state = FAILED; return FAIL; case INIT9LOAD: case READ9LOAD: panic("end 9load"); default: panic("bootdone"); } b->state = FAILED; return FAIL; }