...

Source file src/golang.org/x/net/internal/iana/gen.go

Documentation: golang.org/x/net/internal/iana

     1  // Copyright 2013 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build ignore
     6  
     7  //go:generate go run gen.go
     8  
     9  // This program generates internet protocol constants and tables by
    10  // reading IANA protocol registries.
    11  package main
    12  
    13  import (
    14  	"bytes"
    15  	"encoding/xml"
    16  	"fmt"
    17  	"go/format"
    18  	"io"
    19  	"net/http"
    20  	"os"
    21  	"strconv"
    22  	"strings"
    23  )
    24  
    25  var registries = []struct {
    26  	url   string
    27  	parse func(io.Writer, io.Reader) error
    28  }{
    29  	{
    30  		"https://www.iana.org/assignments/dscp-registry/dscp-registry.xml",
    31  		parseDSCPRegistry,
    32  	},
    33  	{
    34  		"https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml",
    35  		parseProtocolNumbers,
    36  	},
    37  	{
    38  		"https://www.iana.org/assignments/address-family-numbers/address-family-numbers.xml",
    39  		parseAddrFamilyNumbers,
    40  	},
    41  }
    42  
    43  func main() {
    44  	var bb bytes.Buffer
    45  	fmt.Fprintf(&bb, "// go generate gen.go\n")
    46  	fmt.Fprintf(&bb, "// Code generated by the command above; DO NOT EDIT.\n\n")
    47  	fmt.Fprintf(&bb, "// Package iana provides protocol number resources managed by the Internet Assigned Numbers Authority (IANA).\n")
    48  	fmt.Fprintf(&bb, `package iana // import "golang.org/x/net/internal/iana"`+"\n\n")
    49  	for _, r := range registries {
    50  		resp, err := http.Get(r.url)
    51  		if err != nil {
    52  			fmt.Fprintln(os.Stderr, err)
    53  			os.Exit(1)
    54  		}
    55  		defer resp.Body.Close()
    56  		if resp.StatusCode != http.StatusOK {
    57  			fmt.Fprintf(os.Stderr, "got HTTP status code %v for %v\n", resp.StatusCode, r.url)
    58  			os.Exit(1)
    59  		}
    60  		if err := r.parse(&bb, resp.Body); err != nil {
    61  			fmt.Fprintln(os.Stderr, err)
    62  			os.Exit(1)
    63  		}
    64  		fmt.Fprintf(&bb, "\n")
    65  	}
    66  	b, err := format.Source(bb.Bytes())
    67  	if err != nil {
    68  		fmt.Fprintln(os.Stderr, err)
    69  		os.Exit(1)
    70  	}
    71  	if err := os.WriteFile("const.go", b, 0644); err != nil {
    72  		fmt.Fprintln(os.Stderr, err)
    73  		os.Exit(1)
    74  	}
    75  }
    76  
    77  func parseDSCPRegistry(w io.Writer, r io.Reader) error {
    78  	dec := xml.NewDecoder(r)
    79  	var dr dscpRegistry
    80  	if err := dec.Decode(&dr); err != nil {
    81  		return err
    82  	}
    83  	fmt.Fprintf(w, "// %s, Updated: %s\n", dr.Title, dr.Updated)
    84  	fmt.Fprintf(w, "const (\n")
    85  	for _, dr := range dr.escapeDSCP() {
    86  		fmt.Fprintf(w, "DiffServ%s = %#02x", dr.Name, dr.Value)
    87  		fmt.Fprintf(w, "// %s\n", dr.OrigName)
    88  	}
    89  	for _, er := range dr.escapeECN() {
    90  		fmt.Fprintf(w, "%s = %#02x", er.Descr, er.Value)
    91  		fmt.Fprintf(w, "// %s\n", er.OrigDescr)
    92  	}
    93  	fmt.Fprintf(w, ")\n")
    94  	return nil
    95  }
    96  
    97  type dscpRegistry struct {
    98  	XMLName    xml.Name `xml:"registry"`
    99  	Title      string   `xml:"title"`
   100  	Updated    string   `xml:"updated"`
   101  	Note       string   `xml:"note"`
   102  	Registries []struct {
   103  		Title      string `xml:"title"`
   104  		Registries []struct {
   105  			Title   string `xml:"title"`
   106  			Records []struct {
   107  				Name  string `xml:"name"`
   108  				Space string `xml:"space"`
   109  			} `xml:"record"`
   110  		} `xml:"registry"`
   111  		Records []struct {
   112  			Value string `xml:"value"`
   113  			Descr string `xml:"description"`
   114  		} `xml:"record"`
   115  	} `xml:"registry"`
   116  }
   117  
   118  type canonDSCPRecord struct {
   119  	OrigName string
   120  	Name     string
   121  	Value    int
   122  }
   123  
   124  func (drr *dscpRegistry) escapeDSCP() []canonDSCPRecord {
   125  	var drs []canonDSCPRecord
   126  	for _, preg := range drr.Registries {
   127  		if !strings.Contains(preg.Title, "Differentiated Services Field Codepoints") {
   128  			continue
   129  		}
   130  		for _, reg := range preg.Registries {
   131  			if !strings.Contains(reg.Title, "Pool 1 Codepoints") {
   132  				continue
   133  			}
   134  			drs = make([]canonDSCPRecord, len(reg.Records))
   135  			sr := strings.NewReplacer(
   136  				"+", "",
   137  				"-", "",
   138  				"/", "",
   139  				".", "",
   140  				" ", "",
   141  			)
   142  			for i, dr := range reg.Records {
   143  				s := strings.TrimSpace(dr.Name)
   144  				drs[i].OrigName = s
   145  				drs[i].Name = sr.Replace(s)
   146  				n, err := strconv.ParseUint(dr.Space, 2, 8)
   147  				if err != nil {
   148  					continue
   149  				}
   150  				drs[i].Value = int(n) << 2
   151  			}
   152  		}
   153  	}
   154  	return drs
   155  }
   156  
   157  type canonECNRecord struct {
   158  	OrigDescr string
   159  	Descr     string
   160  	Value     int
   161  }
   162  
   163  func (drr *dscpRegistry) escapeECN() []canonECNRecord {
   164  	var ers []canonECNRecord
   165  	for _, reg := range drr.Registries {
   166  		if !strings.Contains(reg.Title, "ECN Field") {
   167  			continue
   168  		}
   169  		ers = make([]canonECNRecord, len(reg.Records))
   170  		sr := strings.NewReplacer(
   171  			"Capable", "",
   172  			"Not-ECT", "",
   173  			"ECT(1)", "",
   174  			"ECT(0)", "",
   175  			"CE", "",
   176  			"(", "",
   177  			")", "",
   178  			"+", "",
   179  			"-", "",
   180  			"/", "",
   181  			".", "",
   182  			" ", "",
   183  		)
   184  		for i, er := range reg.Records {
   185  			s := strings.TrimSpace(er.Descr)
   186  			ers[i].OrigDescr = s
   187  			ss := strings.Split(s, " ")
   188  			if len(ss) > 1 {
   189  				ers[i].Descr = strings.Join(ss[1:], " ")
   190  			} else {
   191  				ers[i].Descr = ss[0]
   192  			}
   193  			ers[i].Descr = sr.Replace(er.Descr)
   194  			n, err := strconv.ParseUint(er.Value, 2, 8)
   195  			if err != nil {
   196  				continue
   197  			}
   198  			ers[i].Value = int(n)
   199  		}
   200  	}
   201  	return ers
   202  }
   203  
   204  func parseProtocolNumbers(w io.Writer, r io.Reader) error {
   205  	dec := xml.NewDecoder(r)
   206  	var pn protocolNumbers
   207  	if err := dec.Decode(&pn); err != nil {
   208  		return err
   209  	}
   210  	prs := pn.escape()
   211  	prs = append([]canonProtocolRecord{{
   212  		Name:  "IP",
   213  		Descr: "IPv4 encapsulation, pseudo protocol number",
   214  		Value: 0,
   215  	}}, prs...)
   216  	fmt.Fprintf(w, "// %s, Updated: %s\n", pn.Title, pn.Updated)
   217  	fmt.Fprintf(w, "const (\n")
   218  	for _, pr := range prs {
   219  		if pr.Name == "" {
   220  			continue
   221  		}
   222  		fmt.Fprintf(w, "Protocol%s = %d", pr.Name, pr.Value)
   223  		s := pr.Descr
   224  		if s == "" {
   225  			s = pr.OrigName
   226  		}
   227  		fmt.Fprintf(w, "// %s\n", s)
   228  	}
   229  	fmt.Fprintf(w, ")\n")
   230  	return nil
   231  }
   232  
   233  type protocolNumbers struct {
   234  	XMLName  xml.Name `xml:"registry"`
   235  	Title    string   `xml:"title"`
   236  	Updated  string   `xml:"updated"`
   237  	RegTitle string   `xml:"registry>title"`
   238  	Note     string   `xml:"registry>note"`
   239  	Records  []struct {
   240  		Value string `xml:"value"`
   241  		Name  string `xml:"name"`
   242  		Descr string `xml:"description"`
   243  	} `xml:"registry>record"`
   244  }
   245  
   246  type canonProtocolRecord struct {
   247  	OrigName string
   248  	Name     string
   249  	Descr    string
   250  	Value    int
   251  }
   252  
   253  func (pn *protocolNumbers) escape() []canonProtocolRecord {
   254  	prs := make([]canonProtocolRecord, len(pn.Records))
   255  	sr := strings.NewReplacer(
   256  		"-in-", "in",
   257  		"-within-", "within",
   258  		"-over-", "over",
   259  		"+", "P",
   260  		"-", "",
   261  		"/", "",
   262  		".", "",
   263  		" ", "",
   264  	)
   265  	for i, pr := range pn.Records {
   266  		if strings.Contains(pr.Name, "Deprecated") ||
   267  			strings.Contains(pr.Name, "deprecated") {
   268  			continue
   269  		}
   270  		prs[i].OrigName = pr.Name
   271  		s := strings.TrimSpace(pr.Name)
   272  		switch pr.Name {
   273  		case "ISIS over IPv4":
   274  			prs[i].Name = "ISIS"
   275  		case "manet":
   276  			prs[i].Name = "MANET"
   277  		default:
   278  			prs[i].Name = sr.Replace(s)
   279  		}
   280  		ss := strings.Split(pr.Descr, "\n")
   281  		for i := range ss {
   282  			ss[i] = strings.TrimSpace(ss[i])
   283  		}
   284  		if len(ss) > 1 {
   285  			prs[i].Descr = strings.Join(ss, " ")
   286  		} else {
   287  			prs[i].Descr = ss[0]
   288  		}
   289  		prs[i].Value, _ = strconv.Atoi(pr.Value)
   290  	}
   291  	return prs
   292  }
   293  
   294  func parseAddrFamilyNumbers(w io.Writer, r io.Reader) error {
   295  	dec := xml.NewDecoder(r)
   296  	var afn addrFamilylNumbers
   297  	if err := dec.Decode(&afn); err != nil {
   298  		return err
   299  	}
   300  	afrs := afn.escape()
   301  	fmt.Fprintf(w, "// %s, Updated: %s\n", afn.Title, afn.Updated)
   302  	fmt.Fprintf(w, "const (\n")
   303  	for _, afr := range afrs {
   304  		if afr.Name == "" {
   305  			continue
   306  		}
   307  		fmt.Fprintf(w, "AddrFamily%s = %d", afr.Name, afr.Value)
   308  		fmt.Fprintf(w, "// %s\n", afr.Descr)
   309  	}
   310  	fmt.Fprintf(w, ")\n")
   311  	return nil
   312  }
   313  
   314  type addrFamilylNumbers struct {
   315  	XMLName  xml.Name `xml:"registry"`
   316  	Title    string   `xml:"title"`
   317  	Updated  string   `xml:"updated"`
   318  	RegTitle string   `xml:"registry>title"`
   319  	Note     string   `xml:"registry>note"`
   320  	Records  []struct {
   321  		Value string `xml:"value"`
   322  		Descr string `xml:"description"`
   323  	} `xml:"registry>record"`
   324  }
   325  
   326  type canonAddrFamilyRecord struct {
   327  	Name  string
   328  	Descr string
   329  	Value int
   330  }
   331  
   332  func (afn *addrFamilylNumbers) escape() []canonAddrFamilyRecord {
   333  	afrs := make([]canonAddrFamilyRecord, len(afn.Records))
   334  	sr := strings.NewReplacer(
   335  		"IP version 4", "IPv4",
   336  		"IP version 6", "IPv6",
   337  		"Identifier", "ID",
   338  		"-", "",
   339  		"-", "",
   340  		"/", "",
   341  		".", "",
   342  		" ", "",
   343  	)
   344  	for i, afr := range afn.Records {
   345  		if strings.Contains(afr.Descr, "Unassigned") ||
   346  			strings.Contains(afr.Descr, "Reserved") {
   347  			continue
   348  		}
   349  		afrs[i].Descr = afr.Descr
   350  		s := strings.TrimSpace(afr.Descr)
   351  		switch s {
   352  		case "IP (IP version 4)":
   353  			afrs[i].Name = "IPv4"
   354  		case "IP6 (IP version 6)":
   355  			afrs[i].Name = "IPv6"
   356  		case "AFI for L2VPN information":
   357  			afrs[i].Name = "L2VPN"
   358  		case "E.164 with NSAP format subaddress":
   359  			afrs[i].Name = "E164withSubaddress"
   360  		case "MT IP: Multi-Topology IP version 4":
   361  			afrs[i].Name = "MTIPv4"
   362  		case "MAC/24":
   363  			afrs[i].Name = "MACFinal24bits"
   364  		case "MAC/40":
   365  			afrs[i].Name = "MACFinal40bits"
   366  		case "IPv6/64":
   367  			afrs[i].Name = "IPv6Initial64bits"
   368  		default:
   369  			n := strings.Index(s, "(")
   370  			if n > 0 {
   371  				s = s[:n]
   372  			}
   373  			n = strings.Index(s, ":")
   374  			if n > 0 {
   375  				s = s[:n]
   376  			}
   377  			afrs[i].Name = sr.Replace(s)
   378  		}
   379  		afrs[i].Value, _ = strconv.Atoi(afr.Value)
   380  	}
   381  	return afrs
   382  }
   383  

View as plain text