Пример #1
0
func ParseNS(name string, ttl int32, rdclass string, zstate *ZoneState, s *scanner.Scanner) (rdtype.Rdtyper, error) {
	cur := <-s.Next()
	if err := goodToken(&cur); err != nil {
		return nil, err
	}
	targetName := trueName(zstate, cur.Value)
	if err := requireDNSName(&cur.Value); err != nil {
		return nil, err
	}
	ns := rdtype.NS{name, ttl, targetName}
	return rdtype.Rdtyper(ns), nil
}
Пример #2
0
func parseSOAInt32(s *scanner.Scanner, cur scanner.Token) (int32, error) {
	cur = <-s.Next()
	if err := goodToken(&cur); err != nil {
		return 0, err
	}
	i, err := requireInt32(cur.Value)
	if err != nil {
		return 0, err
	}
	if err := ClearCommentNewLine(s); err != nil {
		return 0, err
	}
	return i, nil
}
Пример #3
0
func ParseNewLines(s *scanner.Scanner) (bool, error) {
	// ParseNewLines: Consume newlines
	ret := false
	for {
		peek := <-s.Peek()
		//if err := goodToken(&peek); err != nil {return false, err}
		if peek.Value == "\n" {
			ret = true
			<-s.Next()
			continue
		}
		break
	}
	return ret, nil
}
Пример #4
0
func ParseComment(s *scanner.Scanner) (bool, string, error) {
	// ParseComment: Consume a comment if it exists. Stop leaving \n next
	// return:
	//  - bool: if a comment was parsed
	//  - string: the comment that was parsed
	//  - error: errors
	next := <-s.PeekUntil(`[\n;]`)
	if next.Value != ";" {
		return false, "", nil
	}
	for {
		peek := <-s.Peek()
		if peek.Value == "\n" || peek.End {
			break
		}
		<-s.Next()
	}
	return true, "", nil
}
Пример #5
0
func ParseDirective(zstate *ZoneState, s *scanner.Scanner) ([]rdtype.Rdtyper, error) {
	// Assume s.Peek() is looking at $<something>  #someoneelsesjob
	// $TTL sets zstate.Ttl
	// $ORIGIN sets zstate.Origin
	// $GENERATE returns []rdtype.RDtyper
	var value string
	directive := (<-s.Next()).Value
	switch directive {
	case "$TTL":
		value = (<-s.Next()).Value
		if ttl, err := strconv.ParseInt(value, 0, 64); err == nil {
			zstate.Ttl = int32(ttl)
		} else {
			return nil, fmt.Errorf("Unable to parse value '%s' as valid ttl\n", ttl)
		}
		if _, _, err := ParseComment(s); err != nil {
			return nil, err
		}
	case "$ORIGIN":
		value = (<-s.Next()).Value
		if err := requireDNSName(&value); err != nil {
			return nil, err
		}
		zstate.Origin = trueName(zstate, value)
		if _, _, err := ParseComment(s); err != nil {
			return nil, err
		}
	case "$GENERATE":
		//TODO
		goto ERROR
	}

	goto SUCCESS
ERROR:
	return nil, fmt.Errorf("Unknown directive '%s'\n", directive)
SUCCESS:
	return nil, nil
}
Пример #6
0
func ParseRecord(zstate *ZoneState, s *scanner.Scanner, dispatch *rdTypeDispatch) (rdtype.Rdtyper, error) {
	// Parse Record beginning of record then dispatch the record's specific parse function

	// Three Cases
	// name ttl  class type         -- case 2
	// 0    1    2     3
	//      name class type         -- case 1
	//      0    1     2
	//      ttl  class type         -- case 1
	//      0    1     2
	//           class type         -- case 0
	//           0     1
	// If 0 & 1 are class and type  -- case 0
	//  $ORIGIN and $TTL
	// If 1 & 2 are class and type  -- case 1
	//  if ttl is int32
	//      $ORIGIN and ttl
	//  else
	//      name and ttl
	// If 2 & 3 are class and type  -- case 2
	//  name and ttl

	peeker := s.Peekn(4)
	tokens := [...]scanner.Token{
		<-peeker,
		<-peeker,
		<-peeker,
		<-peeker,
	}

	var ttl int32
	var name, rdclass, rdtype_ string
	var valid_class bool

	for i := 0; i < 3; i++ {
		cur := tokens[i]
		next := tokens[i+1]

		_, valid_class = RDCLASS[strings.ToUpper(cur.Value)]
		_, valid_rdtype := dispatch.RDType[strings.ToUpper(next.Value)]

		rdclass = cur.Value
		rdtype_ = next.Value

		if valid_class && valid_rdtype {
			switch i {
			case 0:
				<-s.Next()
				<-s.Next()
				name = trueName(zstate, "@")
				ttl = zstate.Ttl
				goto DISPATCH
			case 1:
				<-s.Next()
				<-s.Next()
				<-s.Next()
				// ttl class type
				// or
				// name class type
				ttl_, is_ttl := strconv.ParseInt(tokens[0].Value, 0, 64)
				if is_ttl != nil {
					name = trueName(zstate, tokens[0].Value)
					ttl = zstate.Ttl
				} else {
					name = trueName(zstate, "@")
					ttl = int32(ttl_)
				}
				goto DISPATCH
			case 2:
				<-s.Next()
				<-s.Next()
				<-s.Next()
				<-s.Next()
				name = trueName(zstate, tokens[0].Value)
				ttl_, err := strconv.ParseInt(tokens[1].Value, 0, 64)
				if err != nil {
					return nil, err
				}
				ttl = int32(ttl_)
				goto DISPATCH
			}
		}
	}

	return nil, fmt.Errorf("Could not parse a record!\n")
DISPATCH:
	//fmt.Printf("rdclass='%s' rdtype='%s'\n", rdclass, rdtype_)
	return dispatch.RDType[rdtype_](name, ttl, rdclass, zstate, s)
}
Пример #7
0
func ParseSOA(name string, ttl int32, rdclass string, zstate *ZoneState, s *scanner.Scanner) (rdtype.Rdtyper, error) {
	// Assume scanner is currently on rdtype
	// We expect to see:
	// primary contact (serial, refresh, retry, exprire, minimum)
	// Parse out comments and ignore them
	//fmt.Printf("ParseSOA rdclass='%s' rdtype='%s'\n", rdclass, "SOA")
	cur := <-s.Next()
	if err := goodToken(&cur); err != nil {
		return nil, err
	}
	primary := trueName(zstate, cur.Value)
	//fmt.Printf("primary=%s\n", primary)

	cur = <-s.NextUntil(`[\n\(]`)
	if err := goodToken(&cur); err != nil {
		return nil, err
	}
	contact := trueName(zstate, cur.Value)
	//fmt.Printf("contact=%s\n", contact)

	if err := ClearCommentNewLine(s); err != nil {
		return nil, err
	}

	//fmt.Printf("peek='%s'\n", (<-s.Peek()).Value)
	cur = <-s.NextUntil(`[\(\n]`)
	//fmt.Printf("lparen='%s'\n", cur.Value)
	//fmt.Printf("peek='%s'\n", (<-s.Peek()).Value)
	if err := goodToken(&cur); err != nil {
		return nil, err
	}
	if cur.Value != "(" {
		return nil, fmt.Errorf(
			"Expected '(' in SOA definition but instead found '%s'\n", cur.Value)
	}

	if err := ClearCommentNewLine(s); err != nil {
		return nil, err
	}

	serial, err := parseSOAInt32(s, cur)
	if err != nil {
		return nil, err
	}
	//fmt.Printf("serial=%d\n", serial)

	refresh, err := parseSOAInt32(s, cur)
	if err != nil {
		return nil, err
	}
	//fmt.Printf("refresh=%d\n", refresh)

	retry, err := parseSOAInt32(s, cur)
	if err != nil {
		return nil, err
	}
	//fmt.Printf("retry=%d\n", retry)

	expire, err := parseSOAInt32(s, cur)
	if err != nil {
		return nil, err
	}
	//fmt.Printf("expire=%d\n", expire)

	cur = <-s.NextUntil(`[\)\n]`)
	if err := goodToken(&cur); err != nil {
		return nil, err
	}
	minimum, err := requireInt32(cur.Value)
	if err != nil {
		return nil, err
	}
	//fmt.Printf("minimum=%d\n", minimum)

	//fmt.Printf("-------------\n")
	if err := ClearCommentNewLine(s); err != nil {
		return nil, err
	}

	cur = <-s.Next()
	if cur.Value != ")" {
		return nil, fmt.Errorf(
			"Expected ')' in SOA definition but instead found '%s'\n", cur.Value)
	}
	soa := rdtype.SOA{name, ttl, primary, contact, serial, retry, refresh, expire, minimum}
	return rdtype.Rdtyper(soa), nil
}