gitee.com/ks-custle/core-gm@v0.0.0-20230922171213-b83bdd97b62c/net/internal/iana/gen.go (about)

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