| package provider |
| |
| // Support for the RIPE IRR. |
| // We use the RIPE REST DB API. |
| |
| import ( |
| "context" |
| "encoding/json" |
| "fmt" |
| "io/ioutil" |
| "net/http" |
| |
| pb "code.hackerspace.pl/hscloud/bgpwtf/cccampix/proto" |
| "google.golang.org/grpc/codes" |
| "google.golang.org/grpc/status" |
| ) |
| |
| type ripeResponse struct { |
| Objects struct { |
| Object []ripeObject `json:"object"` |
| } `json:"objects"` |
| } |
| |
| type ripeObject struct { |
| Type string `json:"type"` |
| Attributes struct { |
| Attribute []ripeAttribute `json:"attribute"` |
| } `json:"attributes"` |
| } |
| |
| type ripeAttribute struct { |
| Name string `json:"name"` |
| Value string `json:"value"` |
| } |
| |
| type ripe struct { |
| sem chan struct{} |
| } |
| |
| func NewRIPE(limit int) Provider { |
| return &ripe{ |
| sem: make(chan struct{}, limit), |
| } |
| } |
| |
| func (r *ripe) Query(ctx context.Context, as uint64) (*pb.IRRQueryResponse, error) { |
| r.sem <- struct{}{} |
| defer func() { |
| <-r.sem |
| }() |
| |
| req, err := http.NewRequest("GET", fmt.Sprintf("http://rest.db.ripe.net/ripe/aut-num/AS%d.json", as), nil) |
| if err != nil { |
| return nil, err |
| } |
| |
| req = req.WithContext(ctx) |
| client := http.DefaultClient |
| |
| res, err := client.Do(req) |
| if err != nil { |
| return nil, status.Errorf(codes.Unavailable, "could not run GET to RIPE: %v", err) |
| } |
| defer res.Body.Close() |
| bytes, err := ioutil.ReadAll(res.Body) |
| if err != nil { |
| return nil, status.Errorf(codes.Unavailable, "could not read response from RIPE: %v", err) |
| } |
| |
| data := ripeResponse{} |
| err = json.Unmarshal(bytes, &data) |
| if err != nil { |
| return nil, status.Errorf(codes.Unavailable, "could not decode response from RIPE: %v", err) |
| } |
| |
| if len(data.Objects.Object) != 1 { |
| return nil, status.Error(codes.NotFound, "could not retrieve aut-num from RIPE") |
| } |
| |
| attributes := make([]rpslRawAttribute, len(data.Objects.Object[0].Attributes.Attribute)) |
| |
| for i, attr := range data.Objects.Object[0].Attributes.Attribute { |
| attributes[i].name = attr.Name |
| attributes[i].value = attr.Value |
| } |
| |
| return &pb.IRRQueryResponse{ |
| Source: pb.IRRQueryResponse_SOURCE_RIPE, |
| Attributes: parseAttributes(attributes), |
| }, nil |
| } |